应用启动选择

我们经常会通过一个Intent来启动一个Activity,但是如果有多个Application注册了相同的Action,这时会怎么样呢? Android 为我们提供了选择对话框即把所有的接收到此Action的Application对列表的形式放到对话框中,让用户选择打开哪一个Application。同样的也可以设置默认打开的Application。像Windows中的默认打开方式。

Android系统对于每个Activity的注册信息是如何管理的?

选择应用的对话框是如何打开的?

如何知道哪些Application的Activity注册了相同的Action?

如何知道,我们是选择了哪个Application的哪个Activity,后续又是如何处理的?

。。。。。

这些暂不讨论,后续完善!这里只讨论下,如何把某个Application设置默认启动的:

我们知道实际上在选把应用的对话框上有一个设为默认启动的选项,选中后,我们再选择某个Application,后续就会直接启动默认选中的Application代码是是怎么实现的呢:

frameworks/base/core/java/com/android/internal/app/ResolverActivity.java

 1 protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
 2         if (alwaysCheck) {
 3             // Build a reasonable intent filter, based on what matched.
 4             IntentFilter filter = new IntentFilter();
 5 
 6             if (intent.getAction() != null) {
 7                 filter.addAction(intent.getAction());
 8             }
 9             Set<String> categories = intent.getCategories();
10             if (categories != null) {
11                 for (String cat : categories) {
12                     filter.addCategory(cat);
13                 }
14             }
15             filter.addCategory(Intent.CATEGORY_DEFAULT);
16 
17             int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
18             Uri data = intent.getData();
19             if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
20                 String mimeType = intent.resolveType(this);
21                 if (mimeType != null) {
22                     try {
23                         filter.addDataType(mimeType);
24                     } catch (IntentFilter.MalformedMimeTypeException e) {
25                         Log.w("ResolverActivity", e);
26                         filter = null;
27                     }
28                 }
29             }
30             if (data != null && data.getScheme() != null) {
31                 // We need the data specification if there was no type,
32                 // OR if the scheme is not one of our magical "file:"
33                 // or "content:" schemes (see IntentFilter for the reason).
34                 if (cat != IntentFilter.MATCH_CATEGORY_TYPE
35                         || (!"file".equals(data.getScheme())
36                                 && !"content".equals(data.getScheme()))) {
37                     filter.addDataScheme(data.getScheme());
38     
39                     // Look through the resolved filter to determine which part
40                     // of it matched the original Intent.
41                     Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();
42                     if (aIt != null) {
43                         while (aIt.hasNext()) {
44                             IntentFilter.AuthorityEntry a = aIt.next();
45                             if (a.match(data) >= 0) {
46                                 int port = a.getPort();
47                                 filter.addDataAuthority(a.getHost(),
48                                         port >= 0 ? Integer.toString(port) : null);
49                                 break;
50                             }
51                         }
52                     }
53                     Iterator<PatternMatcher> pIt = ri.filter.pathsIterator();
54                     if (pIt != null) {
55                         String path = data.getPath();
56                         while (path != null && pIt.hasNext()) {
57                             PatternMatcher p = pIt.next();
58                             if (p.match(path)) {
59                                 filter.addDataPath(p.getPath(), p.getType());
60                                 break;
61                             }
62                         }
63                     }
64                 }
65             }
66 
67             if (filter != null) {
68                 final int N = mAdapter.mList.size();
69                 ComponentName[] set = new ComponentName[N];
70                 int bestMatch = 0;
71                 for (int i=0; i<N; i++) {
72                     ResolveInfo r = mAdapter.mList.get(i).ri;
73                     set[i] = new ComponentName(r.activityInfo.packageName,
74                             r.activityInfo.name);
75                     if (r.match > bestMatch) bestMatch = r.match;
76                 }
77                 getPackageManager().addPreferredActivity(filter, bestMatch, set,
78                         intent.getComponent());
79             }
80         }
81 
82         if (intent != null) {
83             startActivity(intent);
84         }
85     }

如上代码即为选中某个Application时的处理,最重要的就是这句getPackageManager().addPreferredActivity(filter, bestMatch, set,intent.getComponent());设置默认的启动项。

下面为自定义的用代码来自动的设置默认的启动项,不用手动的点击设置默认项那么麻烦:

 1 private void setDefaultLauncher() {
 2         
 3         PackageManager pm = null;
 4         IntentFilter intentFilter;
 5         
 6         //check permission
 7         if (PermissionUtils.checkPermission(mContext,
 8                 mContext.getPackageName(),
 9                 "android.permission.SET_PREFERRED_APPLICATIONS")) {
10             pm = getPackageManager();
11             
12             ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>();
13             ArrayList<ComponentName> cnList = new ArrayList<ComponentName>();
14             int number= pm.getPreferredActivities(intentList, cnList, null);
15             LogUtils.d("debug", "the number of distinct IntentFilter records = "
16                     + number);
17             
18             //clean default
19             for (int i = 0; i < cnList.size(); i++) {
20                 intentFilter = intentList.get(i);
21                 if (intentFilter.hasAction(Intent.ACTION_MAIN)
22                         && intentFilter.hasCategory(Intent.CATEGORY_HOME)) {
23                     pm.clearPackagePreferredActivities(cnList.get(i)
24                             .getPackageName());
25                 }
26             }
27 
28             //application list with same action
29             Intent intent = new Intent(Intent.ACTION_MAIN);
30             intent.addCategory(Intent.CATEGORY_HOME);
31             List<ResolveInfo> list = new ArrayList<ResolveInfo>();
32             
33             list = pm.queryIntentActivities(intent,
34                     PackageManager.MATCH_DEFAULT_ONLY);
35             
36             IntentFilter filter = new IntentFilter();
37             filter.addAction(Intent.ACTION_MAIN);
38             filter.addCategory(Intent.CATEGORY_HOME);
39             filter.addCategory(Intent.CATEGORY_DEFAULT);
40             final int N = list.size();
41             ComponentName[] set = new ComponentName[N];
42             int bestMatch = 0;
43             //get best match
44             for (int i = 0; i < N; i++) {
45                 ResolveInfo r = list.get(i);
46                 set[i] = new ComponentName(r.activityInfo.packageName,
47                         r.activityInfo.name);
48                 if (r.match > bestMatch)
49                     bestMatch = r.match;
50             }
51             
52             //add component
53             ComponentName launcher = new ComponentName(
54                     "com.test.switch",
55                     "com.test.switch.TestActivity");
56             
57             pm.addPreferredActivity(filter, bestMatch, set, launcher);
58         } else {
59             LogUtils.d("debug", "no permission");
60         }
61     }
原文地址:https://www.cnblogs.com/pillowzhou/p/4671944.html