05-09 17:01:13.547: I/ActivityManager(3003): START u0 {act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://www.baidu.com cmp=android/com.android.internal.app.ResolverActivity} from pid 5222 05-09 17:01:13.587: I/ActivityManager(3003): Start proc system:ui for activity android/com.android.internal.app.ResolverActivity: pid=15544 uid=1000 gids={41000, 3002, 3001, 3003, 1028, 1015, 1023, 1021, 3004, 3005, 1000, 3009, 1010} 05-09 17:01:14.557: I/ActivityManager(3003): Displayed android/com.android.internal.app.ResolverActivity: +975ms
從ActivityManger輸出Log可以知道是ResolverActivity處理app選擇。
android\frameworks\base\core\java\com\android\internal\app\ResolverActivity.java
protected void onCreate(Bundle savedInstanceState) { // Use a specialized prompt when we're handling the 'Home' app startActivity() final int titleResource; final Intent intent = makeMyIntent(); final Set<String> categories = intent.getCategories(); if (Intent.ACTION_MAIN.equals(intent.getAction()) && categories != null && categories.size() == 1 && categories.contains(Intent.CATEGORY_HOME)) { titleResource = com.android.internal.R.string.whichHomeApplication;//選擇主屏幕應用 } else { titleResource = com.android.internal.R.string.whichApplication;//選擇要使用的應用: } onCreate(savedInstanceState, intent, getResources().getText(titleResource), null, null, true); }
protected void onCreate(Bundle savedInstanceState, Intent intent, CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList, boolean alwaysUseOption) { setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert); super.onCreate(savedInstanceState); try { mLaunchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid( getActivityToken()); } catch (RemoteException e) { mLaunchedFromUid = -1; } mPm = getPackageManager(); mAlwaysUseOption = alwaysUseOption; mMaxColumns = getResources().getInteger(R.integer.config_maxResolverActivityColumns); AlertController.AlertParams ap = mAlertParams; ap.mTitle = title; mPackageMonitor.register(this, getMainLooper(), false); mRegistered = true; final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); mIconDpi = am.getLauncherLargeIconDensity(); mIconSize = am.getLauncherLargeIconSize(); mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList, mLaunchedFromUid);//獲取APP列表 int count = mAdapter.getCount(); if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) { // Gulp! finish(); return; } else if (count > 1) { ap.mView = getLayoutInflater().inflate(R.layout.resolver_list, null); mListView = (ListView) ap.mView.findViewById(R.id.resolver_list); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(this); mListView.setOnItemLongClickListener(new ItemLongClickListener()); if (alwaysUseOption) { mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); } } else if (count == 1) { startActivity(mAdapter.intentForPosition(0)); mPackageMonitor.unregister(); mRegistered = false; finish(); return; } else { ap.mMessage = getResources().getText(R.string.noApplications); } setupAlert(); if (alwaysUseOption) { final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar); if (buttonLayout != null) { buttonLayout.setVisibility(View.VISIBLE); mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always); mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once); } else { mAlwaysUseOption = false; } // Set the initial highlight if there was a preferred or last used choice final int initialHighlight = mAdapter.getInitialHighlight(); if (initialHighlight >= 0) { mListView.setItemChecked(initialHighlight, true); onItemClick(null, null, initialHighlight, 0); // Other entries are not used } } }
點擊“始終”按鈕,設置默認程序
public void onButtonClick(View v) { final int id = v.getId(); startSelected(mListView.getCheckedItemPosition(), id == R.id.button_always); dismiss(); } void startSelected(int which, boolean always) { if (isFinishing()) { return; } ResolveInfo ri = mAdapter.resolveInfoForPosition(which); Intent intent = mAdapter.intentForPosition(which); onIntentSelected(ri, intent, always); finish(); } protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) { if (mAlwaysUseOption && mAdapter.mOrigResolveList != null) { // Build a reasonable intent filter, based on what matched. IntentFilter filter = new IntentFilter(); if (intent.getAction() != null) { filter.addAction(intent.getAction()); } Set<String> categories = intent.getCategories(); if (categories != null) { for (String cat : categories) { filter.addCategory(cat); } } filter.addCategory(Intent.CATEGORY_DEFAULT); int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK; Uri data = intent.getData(); if (cat == IntentFilter.MATCH_CATEGORY_TYPE) { String mimeType = intent.resolveType(this); if (mimeType != null) { try { filter.addDataType(mimeType); } catch (IntentFilter.MalformedMimeTypeException e) { Log.w("ResolverActivity", e); filter = null; } } } if (data != null && data.getScheme() != null) { // We need the data specification if there was no type, // OR if the scheme is not one of our magical "file:" // or "content:" schemes (see IntentFilter for the reason). if (cat != IntentFilter.MATCH_CATEGORY_TYPE || (!"file".equals(data.getScheme()) && !"content".equals(data.getScheme()))) {//注意這裏排除了"file://", "content://" filter.addDataScheme(data.getScheme()); // Look through the resolved filter to determine which part // of it matched the original Intent. Iterator<PatternMatcher> pIt = ri.filter.schemeSpecificPartsIterator(); if (pIt != null) { String ssp = data.getSchemeSpecificPart(); while (ssp != null && pIt.hasNext()) { PatternMatcher p = pIt.next(); if (p.match(ssp)) { filter.addDataSchemeSpecificPart(p.getPath(), p.getType()); break; } } } Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator(); if (aIt != null) { while (aIt.hasNext()) { IntentFilter.AuthorityEntry a = aIt.next(); if (a.match(data) >= 0) { int port = a.getPort(); filter.addDataAuthority(a.getHost(), port >= 0 ? Integer.toString(port) : null); break; } } } pIt = ri.filter.pathsIterator(); if (pIt != null) { String path = data.getPath(); while (path != null && pIt.hasNext()) { PatternMatcher p = pIt.next(); if (p.match(path)) { filter.addDataPath(p.getPath(), p.getType()); break; } } } } } if (filter != null) { final int N = mAdapter.mOrigResolveList.size(); ComponentName[] set = new ComponentName[N]; int bestMatch = 0; for (int i=0; i<N; i++) { ResolveInfo r = mAdapter.mOrigResolveList.get(i); set[i] = new ComponentName(r.activityInfo.packageName, r.activityInfo.name); if (r.match > bestMatch) bestMatch = r.match; } if (alwaysCheck) { getPackageManager().addPreferredActivity(filter, bestMatch, set, intent.getComponent());//設置默認 } else { try { AppGlobals.getPackageManager().setLastChosenActivity(intent, intent.resolveTypeIfNeeded(getContentResolver()), PackageManager.MATCH_DEFAULT_ONLY, filter, bestMatch, intent.getComponent()); } catch (RemoteException re) { Log.d(TAG, "Error calling setLastChosenActivity\n" + re); } } } } if (intent != null) { startActivity(intent); } }
1
|
packages/apps/Provision/src/com/android/DefaultActivity.java |
1
|
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java |
1
|
frameworks\base\services\java\com\android\server\am\ActivityManagerService.java |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
private void setDefaultLauncher() { // get default component String packageName = "com.coship.factorytest" ; //默認launcher包名 String className = "com.coship.factorytest.MainActivity" ; ////默認launcher入口 IPackageManager pm = ActivityThread.getPackageManager(); //判斷指定的launcher是否存在 if (hasApkInstalled(packageName)) { Slog.i(TAG, "defautl packageName = " + packageName + ", default className = " + className); //清除當前默認launcher ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>(); ArrayList<ComponentName> cnList = new ArrayList<ComponentName>(); mContext.getPackageManager().getPreferredActivities(intentList, cnList, null ); IntentFilter dhIF = null ; for ( int i = 0 ; i < cnList.size(); i++) { dhIF = intentList.get(i); if (dhIF.hasAction(Intent.ACTION_MAIN) && dhIF.hasCategory(Intent.CATEGORY_HOME)) { mContext.getPackageManager().clearPackagePreferredActivities(cnList.get(i).getPackageName()); } } //獲取所有launcher activity Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); List<ResolveInfo> list = new ArrayList<ResolveInfo>(); try { list = pm.queryIntentActivities(intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), PackageManager.MATCH_DEFAULT_ONLY); } catch (RemoteException e) { throw new RuntimeException( "Package manager has died" , e); } // get all components and the best match IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_MAIN); filter.addCategory(Intent.CATEGORY_HOME); filter.addCategory(Intent.CATEGORY_DEFAULT); final int N = list.size(); Slog.d(TAG, "N:::::hyhyhyhy:::: = " + N); //設置默認launcher ComponentName launcher = new ComponentName(packageName, className); ComponentName[] set = new ComponentName[N]; int defaultMatch = 0 ; for ( int i = 0 ; i < N; i++) { ResolveInfo r = list.get(i); set[i] = new ComponentName(r.activityInfo.packageName, r.activityInfo.name); Slog.d(TAG, "r.activityInfo.packageName:::::hyhyhyhy:::: = " + r.activityInfo.packageName); Slog.d(TAG, "r.activityInfo.name:::::hyhyhyhy:::: = " + r.activityInfo.name); if (launcher.getClassName().equals(r.activityInfo.name)) { defaultMatch = r.match; } } try { pm.addPreferredActivity(filter, defaultMatch, set, launcher); } catch (RemoteException e) { throw new RuntimeException( "com.coship.factorytest.MainActivity : Package manager has died" , e); } } //end if } private static boolean hasApkInstalled(String pkgname) { try { mSelf.mContext.getPackageManager().getPackageInfo(pkgname, 0 ); } catch (Exception e) { Slog.d(TAG, "PackageManager.NameNotFoundException: = " + e.getMessage()); return false ; } return true ; } |
1
|
boolean startHomeActivityLocked() |
1
|
setDefaultLauncher() |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
boolean startHomeActivityLocked() { if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL && mTopAction == null ) { // We are running in factory test mode, but unable to find // the factory test app, so just sit around displaying the // error message and don't try to start anything. return false ; } /////////////////////////////////////////// setDefaultLauncher(); /////////////////////////////////////////// Intent intent = new Intent( mTopAction, mTopData != null ? Uri.parse(mTopData) : null ); intent.setComponent(mTopComponent); if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { intent.addCategory(Intent.CATEGORY_HOME); } ActivityInfo aInfo = intent.resolveActivityInfo(mContext.getPackageManager(), STOCK_PM_FLAGS); if (aInfo != null ) { intent.setComponent( new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); // Don't do this if the home app is currently being // instrumented. ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid); if (app == null || app.instrumentationClass == null ) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); mMainStack.startActivityLocked( null , intent, null , null , 0 , aInfo, null , null , 0 , 0 , 0 , false , false , null ); } } return true ; } |
1
|
frameworks\base\core\java\com\android\internal\app\ResolverActivity.java |