編輯:關於Android編程
一般情況下,為了讓用戶更方便的打開應用,程序會在桌面上生成一些快捷方式。
本來呢,如果是原生的桌面,其實是十分簡單,直接調用系統相關的API就行了。但是眾多的系統廠商以及眾多第三方自己定制的桌面(Launcher),導致在適配、兼容方面存在很多問題。
比如,有些桌面無法刪除快捷方式(比如小米),有些桌面無法生成快捷方式(比如錘子),有些系統無法更新桌面圖標(比如華為榮耀6)。
在升級、降級的時候快捷方式發生變化;比如,全部變成應用的主圖標,升級、降級後點擊快捷方式沒有反應,刪除應用後無法刪除快捷方式。
很多問題都是需要解決的,雖然有些由於系統限制,沒有辦法搞定所有的,但是仍然需要尋求一個最優的方案。這也就是本文需要討論的問題。
本文說指的快捷方式是指應用桌面快捷方式,不包含長按彈出的生成快捷方式。
快捷方式所有信息都是存在於launcher的favorite表。一般需要用到的字段為_id,title,intent,iconResource,icon,分別表示 快捷方式名稱,快捷方式intent,快捷方式圖標(本地),快捷方式圖標(data二進制壓縮數據)。
兩個intent數據如下

數據可以通過SQLite Editor查看,需要已經ROOT的手機
在AndroidManifest.xml增加權限
同時,根據Intent是隱式還是顯示在相關的Activity聲明相關的intent-filter。
相關代碼:


跟增加快捷方式一樣,也是需要增加權限的。加上
相關代碼:

需要增加權限
如果適配所有桌面,請添加附錄中第二條所列出的權限。
/**
*更新桌面快捷方式圖標,不一定所有圖標都有效
*如果快捷方式不存在,則不更新
.
*/
publicstaticvoidupdateShortcutIcon(Contextcontext,Stringtitle,Intentintent,Bitmapbitmap){
if(bitmap==null){
XLog.i(TAG,"updateshortcuticon,bitmapempty");
return;
}
try{
finalContentResolvercr=context.getContentResolver();
StringBuilderuriStr=newStringBuilder();
StringurlTemp="";
Stringauthority=LauncherUtil.getAuthorityFromPermissionDefault(context);
if(authority==null||authority.trim().equals("")){
authority=LauncherUtil.getAuthorityFromPermission(context,LauncherUtil.getCurrentLauncherPackageName(context)+".permission.READ_SETTINGS");
}
uriStr.append("content://");
if(TextUtils.isEmpty(authority)){
intsdkInt=android.os.Build.VERSION.SDK_INT;
if(sdkInt<8){//Android2.1.x(API7)以及以下的
uriStr.append("com.android.launcher.settings");
}elseif(sdkInt<19){//Android4.4以下
uriStr.append("com.android.launcher2.settings");
}else{//4.4以及以上
uriStr.append("com.android.launcher3.settings");
}
}else{
uriStr.append(authority);
}
urlTemp=uriStr.toString();
uriStr.append("/favorites?notify=true");
Uriuri=Uri.parse(uriStr.toString());
Cursorc=cr.query(uri,newString[]{"_id","title","intent"},
"title=?andintent=?",
newString[]{title,intent.toUri(0)},null);
intindex=-1;
if(c!=null&&c.getCount()>0){
c.moveToFirst();
index=c.getInt(0);//獲得圖標索引
ContentValuescv=newContentValues();
cv.put("icon",flattenBitmap(bitmap));
Uriuri2=Uri.parse(urlTemp+"/favorites/"+index+"?notify=true");
inti=context.getContentResolver().update(uri2,cv,null,null);
context.getContentResolver().notifyChange(uri,null);//此處不能用uri2,是個坑
XLog.i(TAG,"updateok:affected"+i+"rows,indexis"+index);
}else{
XLog.i(TAG,"updateresultfailed");
}
if(c!=null&&!c.isClosed()){
c.close();
}
}catch(Exceptionex){
ex.printStackTrace();
XLog.i(TAG,"updateshortcuticon,geterrors:"+ex.getMessage());
}
}
privatestaticbyte[]flattenBitmap(Bitmapbitmap){
//Trygoguesstimatehowmuchspacetheiconwilltakewhenserialized
//toavoidunnecessaryallocations/copiesduringthewrite.
intsize=bitmap.getWidth()*bitmap.getHeight()*4;
ByteArrayOutputStreamout=newByteArrayOutputStream(size);
try{
bitmap.compress(Bitmap.CompressFormat.PNG,100,out);
out.flush();
out.close();
returnout.toByteArray();
}catch(IOExceptione){
XLog.w(TAG,"Couldnotwriteicon");
returnnull;
}
}
需要增加的權限同修改快捷方式
雖然說通過SharePreference來保證快捷方式不會重復創建,以及通過shortcutIntent.putExtra(“duplicate”, false)也可以確保,但是為了萬無一失,還是可以通過去查詢數據判斷快捷方式是否存在,來避免重復創建。 代碼如下:
/**
*檢查快捷方式是否存在
*注意:有些手機無法判斷是否已經創建過快捷方式
*因此,在創建快捷方式時,請添加
*shortcutIntent.putExtra("duplicate",false);//不允許重復創建
*最好使用{@link#isShortCutExist(Context,String,Intent)}
*進行判斷,因為可能有些應用生成的快捷方式名稱是一樣的的
*此處需要在AndroidManifest.xml中配置相關的桌面權限信息
*錯誤信息已捕獲
*/
publicstaticbooleanisShortCutExist(Contextcontext,Stringtitle){
booleanresult=false;
try{
finalContentResolvercr=context.getContentResolver();
StringBuilderuriStr=newStringBuilder();
Stringauthority=LauncherUtil.getAuthorityFromPermissionDefault(context);
if(authority==null||authority.trim().equals("")){
authority=LauncherUtil.getAuthorityFromPermission(context,LauncherUtil.getCurrentLauncherPackageName(context)+".permission.READ_SETTINGS");
}
uriStr.append("content://");
if(TextUtils.isEmpty(authority)){
intsdkInt=android.os.Build.VERSION.SDK_INT;
if(sdkInt<8){//Android2.1.x(API7)以及以下的
uriStr.append("com.android.launcher.settings");
}elseif(sdkInt<19){//Android4.4以下
uriStr.append("com.android.launcher2.settings");
}else{//4.4以及以上
uriStr.append("com.android.launcher3.settings");
}
}else{
uriStr.append(authority);
}
uriStr.append("/favorites?notify=true");
Uriuri=Uri.parse(uriStr.toString());
Cursorc=cr.query(uri,newString[]{"title"},
"title=?",
newString[]{title},null);
if(c!=null&&c.getCount()>0){
result=true;
}
if(c!=null&&!c.isClosed()){
c.close();
}
}catch(Exceptione){
e.printStackTrace();
result=false;
}
returnresult;
}
/**
*不一定所有的手機都有效,因為國內大部分手機的桌面不是系統原生的
*更多請參考{@link#isShortCutExist(Context,String)}
*桌面有兩種,系統桌面(ROM自帶)與第三方桌面,一般只考慮系統自帶
*第三方桌面如果沒有實現系統響應的方法是無法判斷的,比如GO桌面
*此處需要在AndroidManifest.xml中配置相關的桌面權限信息
*錯誤信息已捕獲
*/
publicstaticbooleanisShortCutExist(Contextcontext,Stringtitle,Intentintent){
booleanresult=false;
try{
finalContentResolvercr=context.getContentResolver();
StringBuilderuriStr=newStringBuilder();
Stringauthority=LauncherUtil.getAuthorityFromPermissionDefault(context);
if(authority==null||authority.trim().equals("")){
authority=LauncherUtil.getAuthorityFromPermission(context,LauncherUtil.getCurrentLauncherPackageName(context)+".permission.READ_SETTINGS");
}
uriStr.append("content://");
if(TextUtils.isEmpty(authority)){
intsdkInt=android.os.Build.VERSION.SDK_INT;
if(sdkInt<8){//Android2.1.x(API7)以及以下的
uriStr.append("com.android.launcher.settings");
}elseif(sdkInt<19){//Android4.4以下
uriStr.append("com.android.launcher2.settings");
}else{//4.4以及以上
uriStr.append("com.android.launcher3.settings");
}
}else{
uriStr.append(authority);
}
uriStr.append("/favorites?notify=true");
Uriuri=Uri.parse(uriStr.toString());
Cursorc=cr.query(uri,newString[]{"title","intent"},
"title=?andintent=?",
newString[]{title,intent.toUri(0)},null);
if(c!=null&&c.getCount()>0){
result=true;
}
if(c!=null&&!c.isClosed()){
c.close();
}
}catch(Exceptionex){
result=false;
ex.printStackTrace();
}
returnresult;
}
所有的快捷方式Intent如果不是之前版本的存在很大問題,絕對不要改變參數,否則升級或者降級時快捷方式會出現問題;
同時,盡可能的采用隱式調用,自定義CATEGORY,而不是自定義ACTION,ACTION參數一定要為ACTION_MAIN,否則有些手機在卸載時無法刪除快捷方式(WTF)。
Android應用中實現手勢控制圖片縮放的完全攻略
一、概述現在app中,圖片預覽功能肯定是少不了的,用戶基本已經形成條件反射,看到小圖,點擊看大圖,看到大圖兩個手指開始進行放大,放大後,開始移動到指定部位~~~我相信看圖
Android網絡編程的Socket通信總結
創建服務器端的步驟:1,指定端口實例化一個ServerSocket2,調用ServerSocket的accept方法等待連接期間阻塞3,獲取位於底層的Socket流進行讀
android開發之記錄ListView滾動位置
這個問題本身不難,但是由於項目中的需求太過於復雜,結果導致這個問題變得不是那麼容易實現。在網上一搜,結果如下:int scrollPos = refreshListVie
鵝廠系列一 : 仿QQ側滑菜單
好了,跟隨潮流,還是先看下效果,不然可能都沒人想看下去了(不會看到效果後不想看了吧O(∩_∩)O~)嗯,就是讓左面板在主面板的下面,所以我們自定義的控件S