Android自我總結之快捷方式


引言
使用Android的知道,有快捷方式這么一說,可以通過長按桌面來添加,也有的是第一次運行時候詢問是否需要安裝,有的直接放在桌面(MIUI是直接放在桌面的),那么為了驅動用戶使用,有些應用在安裝以后便直接安裝了快捷方式,還有些應用是在用戶第一次進入的時候,詢問用戶是否安裝快捷方式,那么接下來就看看快捷方式的實現。
 
安裝即帶
這個實現方法比較簡單,直接在AndroidManifest.xml里面就可申明
 
 1          < activity-alias
 2               android:name ="demoAlias"
 3              android:icon ="@drawable/logo"
 4              android:label ="demoAliasLabel"
 5              android:targetActivity =".MainActivity"   >
 6              < intent-filter >
 7                  < action  android:name ="android.intent.action.MAIN"   />
 8 
 9                  < category  android:name ="android.intent.category.DEFAULT"   />
10                  < category  android:name ="android.intent.category.LAUNCHER"   />
11              </ intent-filter >
12          </ activity-alias >
 
name表示快捷方式顯示的名字
icon表示快捷方式圖標
targetActivity表示點擊快捷方式啟動的活動
這個表情直接申明在Application中即可,有一點需要說明的是從快捷方式進入和從默認桌面Activity進入,對於Application有一些參數是有差異的,例如
getIntent().getComponent().getClassName()
主APP進入:{package}.MainActivity
快捷方式進入:{package}.demoAlias
注意:這種本質上不屬於快捷方式,只是在Launcher中添加了一個APP入口的副本,重點在下面的動態創建。
 
動態創建
方式1:托管給系統桌面的快捷方式來創建
對於Android原生系統,桌面空白處長按可以添加小控件、快捷方式等。點擊快捷方式,里面會呈現申明了快捷方式的APP快捷方式列表。
那么如何申明快捷方式呢?這就是第一步
第一步:申明快捷方式
1          < activity-alias
2               android:name ="DemoShortCutName"
3              android:icon ="@drawable/logo"
4              android:label ="DemoShortCutLabel"
5              android:targetActivity =".DynamicShortcut"   >
6              < intent-filter >
7                  < action  android:name ="android.intent.action.CREATE_SHORTCUT"    />
8              </ intent-filter >
9          </ activity-alias >
快捷方式也是一個Activity,可以看成一個虛擬的Activity不需要實體的承載
name:表示這個Activity的標示,通過getClassName()會獲取name屬性
icon:在桌面快捷方式列表中的圖標
label:在桌面快捷方式列表中的文字
targetActivity:既然說他是一個虛擬的Activity,那么需要制定一個實體,也即快捷方式的啟動
通過申明android.intent.action.CREATE_SHORTCUT申明,讓這個虛擬的Activity加入到桌面快捷方式列表中。
 
如果在桌面快捷方式列表中點擊這個快捷方式,會發現僅僅是啟動了TargetActivity,在桌面上並沒有看到這個快捷方式被添加,那么接下來需要在TargetActivity中去實現這個。
第二步:實現快捷方式的添加
 1      private  void generateShortcut() {
 2          //  快捷方式要啟動的Activity
 3          Intent shortcutIntent =  new Intent();
 4         shortcutIntent.setClassName( thisthis.getClass().getName());
 5         
 6          //  動態生成快捷方式
 7          Intent intent =  new Intent();
 8         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
 9         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "test");
10         Parcelable iconResource = Intent.ShortcutIconResource.fromContext( this,  R.drawable.icon0);
11         intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
12          //  將生成的快捷方式遞交給系統生成桌面快捷方式
13          setResult(RESULT_OK, intent);
14     }
快捷方式的添加方法和在AndroidManifest中申明遠離基本相同。
添加原理知道了,那么在什么時候去觸發添加動作
第三步:結合快捷方式列表中點擊生成快捷方式
TargetActivity可以是單獨為創建快捷方式功能而存在,也可以是應用程序的啟動頁面。那么來看下在啟動頁作為TargetActivity的時候,該如何觸發添加快捷方式,
代碼實現原理是:
1.點擊桌面快捷方式
2.啟動TargetActivity
3.添加快捷方式到桌面。
期望結果是沒有第二步,點擊直接添加到桌面,那么在實現的時候,就可以做下處理:
 1     @Override
 2      protected  void onCreate(Bundle savedInstanceState) {
 3          super.onCreate(savedInstanceState);
 4         setContentView(R.layout.dynamic_shortcut);
 5 
 6          final String intentAction = getIntent().getAction();
 7          if (Intent.ACTION_CREATE_SHORTCUT.equals(intentAction)) {
 8             generateShortcut();
 9             finish();
10              return;
11         }
12     }
這樣的話,就達到了期望的結果,到此為止,快捷方式就添加完畢,如果想做成類似“金山開關,360快捷開關”這樣的,可以專門做個Dialog樣式的Activity來作為TargetActivity。
 
方式2:通過代碼在任意時刻通過任意方式創建
例如通過點擊應用里面的某個Button或者應用程序第一次啟動,或者。。。,這里看下原理
 1      private  void createShortcut() {
 2          //  快捷方式要啟動的Activity
 3          Intent target =  new Intent();
 4         target.setClassName( thisthis.getClass().getName());
 5         
 6          //  動態生成快捷方式
 7          Intent shortcutIntent =  new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
 8         shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "shortcutName"); 
 9         shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext( this,  R.drawable.icon1));
10         shortcutIntent.putExtra("duplicate",  false); 
11         shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, target); 
12         
13          //  利用receiver通知系統創建快捷方式
14          sendBroadcast(shortcutIntent); 
15         
16     }
可以看到,和第一種方式實現基本一樣,只不過通知系統生成的方式不一樣,此處用的是通知。其實第一種方式也可以利用通知來實現。
添加“duplicate”是表示快捷方式不能重復添加,當然這塊和第一種實現方式重復添加不沖突。
那么到這里,第二種方式核心實現完成。
 
擴展
上述僅僅介紹了核心實現,那么對於快捷方式的添加,當然還需要申明創建快捷方式的權限了:
1  < uses-permission  android:name ="com.android.launcher.permission.INSTALL_SHORTCUT"   />
這個當然不能忘掉。
還有對於MIUI這種神奇的rom是沒有快捷方式這一說的,大家測試的時候,多用些不同的rom機器試試。
 
那么既然可以重復創建快捷方式,如果想限制只能有一個快捷方式存在,怎么辦,上面設置“duplicate”屬性只能限制第二種方式通知添加,而且會有提示,且是系統去判斷的,那么我們怎么能自己判斷是否已經存在快捷方式了呢,當然可以,來一次看看。
實現思路可以這么想:快捷方式在桌面,那么如果能獲取系統桌面的應用程序屬性,判斷是否我的應用在被放到了桌面就行。
那么來看下代碼:
 1      private  boolean hasShortcut() {
 2          final String AUTHORITY = "com.android.launcher.settings";
 3          final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true");
 4         Cursor c = getContentResolver().query(
 5                 CONTENT_URI,
 6                  new String[] { "title" },
 7                 "title=?",
 8                  new String[] { "test" },
 9                  null);
10          if (c !=  null && c.moveToNext()) {
11              return  true;
12         }
13          return  false;
14     }
簡單的說明下:
通過Context的getContentResolve獲取系統的共享數據,在共享數據中,查找指定Uri的數據,也即launcher中的favorite表,也即快捷方式表。
然后query的參數是篩選表的title列,並且title=“test”的行數據,如果查詢有結果,表示快捷方式名為test的存在,也即返回快捷方式已經添加到桌面。
那么如果你時間了,如果你的測試機是MIUI,或者HTC等rom,你會發現c為null,怎么回事,解釋下
android系統桌面的基本信息由一個launcher.db的Sqlite數據庫管理,里面有三張表,其中一張表就是favorites。這個db文件一般放在data/data/com.android.launcher(launcher2)文件的databases下。但是對於不同的rom會放在不同的地方,例如MIUI放在data/data/com.miui.home/databases下面,htc放在data/data/com.htc.launcher/databases下面,那么如何用程序來找到這個認證標示呢
 1      private String getAuthorityFromPermission(Context context, String permission) {
 2          if (TextUtils.isEmpty(permission)) {
 3              return  null;
 4         }
 5         List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);
 6          if (packs ==  null) {
 7              return  null;
 8         }
 9          for (PackageInfo pack : packs) {
10             ProviderInfo[] providers = pack.providers;
11              if (providers !=  null) {
12                  for (ProviderInfo provider : providers) {
13                      if (permission.equals(provider.readPermission) || permission.equals(provider.writePermission)) {
14                          return provider.authority;
15                     }
16                 }
17             }
18         }
19          return  null;
20     }
通過Permission來找到這個Authority,那么修改驗證方法:
 1      private  boolean hasShortcut() {
 2          final String AUTHORITY = getAuthorityFromPermission(getApplicationContext(), "com.android.launcher.permission.READ_SETTINGS");
 3          final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true");
 4         Cursor c = getContentResolver().query(
 5                 CONTENT_URI,
 6                  new String[] { "title" },
 7                 "title=?",
 8                  new String[] { "test" },
 9                  null);
10          if (c !=  null && c.moveToNext()) {
11              return  true;
12         }
13          return  false;
14     }
這樣就可以了,對於某些系統,找不到的話,可能是由於權限原因或者是系統文件順壞等,你可以通過es explorer工具去找下該文件,並試着用DDMS去讀取
DDMS讀取文件的時候,我出現了權限問題,參考了 http://www.cnblogs.com/zdz8207/archive/2012/08/31/android-file-explore.html
 
總結
OK,快捷方式通過一天的搜索,試驗,找問題,找機器試,總結完畢,把網上出現的一些問題和解決方案都對應的總結了下,希望對大家有幫組。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM