android設置多個類似APP其中的一個爲默認 設置默認launcher


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);
        }
    }




當系統存在多個launcher時,若沒有設置默認launcher,開機啓動後會彈出提示框,羅列所有launcher,用戶選擇並設置了默認launcher後,按home鍵以及以後重啓都會進入默認的launcher。

現在,我希望系統能直接就進入我設定的launcher而不是彈出框後選擇然後設置


網上大部分的做法就是修改

1
packages/apps/Provision/src/com/android/DefaultActivity.java

1
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java


兩個文件,給個相對比較好看一點的鏈接http://blog.csdn.net/z_guijin/article/details/8964890

我按照這個做不能達到預期的效果,


/////////////////////////////////////////添加內容////////////////////////////////////////

後期修改包名,發現開機自啓動出現問題,然後弄了兩天,終於差不多弄清楚了。果然,欠下的債遲早得還!

其實修改DefaultActivity.java就能夠完成開機自啓動,只是當時我的程序有問題,所以沒有達到預期效果


當然下面修改ActivityManagerService.java也能完成開機自啓動


這兩者的區別在於
DefaultActivity.java只是在第一次啓動時執行,如果修改了默認launcher後不可恢復

ActivityManagerService.java在每次啓動時執行,每次都默認啓動設定的launcher,當然,如果設定的launcher存在的話,設置其他的launcher爲默認會無效,因爲重新啓動時setDefaultLauncher()會將當前默認launcher清除。只有在卸載了設定默認啓動的launcher後才能設置其他launcher爲默認啓動.

//////////////////////////////////////////////////////////////////////////////////////////////////////////


修改多次搜索關鍵字,得到另一篇文章,大致看了下,感覺不會有效,但是已經絕望了就試了試,竟然解決了問題http://blog.csdn.net/jia4525036/article/details/18036765

這篇文章有借鑑之處,直接使用時會發現有些字段是上下文中沒有的,故寫下此文記錄一下。


修改文件

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;
    }

然後在ActivityManagerService類中的

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, nullnull0, aInfo,
                        nullnull000falsefalsenull);
            }
        }
         
         
        return true;
    }

添加後的方法全部內容如上,重新編譯android,燒錄,開機就能夠自動進入自定義的launcher

可以通過系統設置取消該launcher的默認設置,取消之後按home鍵會彈出launcher選擇提示框

1
frameworks\base\core\java\com\android\internal\app\ResolverActivity.java

ResolverActivity類就是選擇打開方式的彈出框

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章