Android如何设置默认的Launcher

时间:2025-01-27 14:04:56

问题

机器装有多个launcher,第一次开机,系统会弹出让用户选择哪个作为默认launcher的对话框,但是客户不希望看到这个框,默认使用其中的一个launcher

涉及代码

frameworks/base/services/core/java/com/android/server/am/
frameworks/base/services/core/java/com/android/server/pm/

修改方法

在ActivityManagerService中的startHomeActivityLocked之前,将客户希望的launcher设置到系统的addPreferredActivity(mPreferredActivities)当中,对应的xml配置文件在/data/system/users/0/ 当中,例如

    <preferred-activities>
        <item name="/.MainActivity" match="100000" always="true" set="2">
            <set name="/.MainActivity" />
            <set name=".launcher3/.Launcher" />
            <filter>
                <action name="" />
                <cat name="" />
                <cat name="" />
            </filter>
        </item>
    </preferred-activities>

修改方法

svn diff 
+    //if no preferered launcher activity exist, set the default one
+    private void setDefaultLauncher(int userId) {
+        // get default component
+        String packageName = "";
+        String className = "";
+        IPackageManager pm = ();
+        //判断指定的launcher是否存在
+               (TAG, "setDefaultLauncher packageName " + packageName + " className " + className);
+        if (hasApkInstalled(packageName)) {
+            (TAG, "default packageName = " + packageName + ", default className = " + className);
+            ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>();
+            ArrayList<ComponentName> cnList = new ArrayList<ComponentName>();
+            ().getPreferredActivities(intentList, cnList, null);
+            IntentFilter dhIF = null;
+            for (int i = 0; i < (); i++) {
+                dhIF = (i);
+                if ((Intent.ACTION_MAIN) && (Intent.CATEGORY_HOME)) {
+                    (TAG, "default launcher exist = " + (i).getPackageName());
+                    return;
+                }
+            }
+            //获取所有launcher activity
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            (Intent.CATEGORY_HOME);
+            (Intent.CATEGORY_DEFAULT);            
+                       List<ResolveInfo> list = new ArrayList<ResolveInfo>();
+            try {
+                list = (intent,
+                (()),
+                STOCK_PM_FLAGS, userId);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Package manager has died", e);
+            }
+            // get all components and the best match
+            IntentFilter filter = new IntentFilter();
+            (Intent.ACTION_MAIN);
+            (Intent.CATEGORY_HOME);
+            (Intent.CATEGORY_DEFAULT);
+            final int N = ();
+            //设置默认launcher
+            ComponentName launcher = new ComponentName(packageName, className);
+            ComponentName[] set = new ComponentName[N];
+            ComponentName[] setLauncher = new ComponentName[2];
+            int defaultMatch = 0;
+            for (int i = 0; i < N; i++) {
+                ResolveInfo r = (i);
+                set[i] = new ComponentName(, );
+                (TAG, "======= " + );
+                (TAG, "========= " + );
+                //if (().equals()) {
+                if(("") != -1) {
+                         continue;
+                 }
+
+               if(("") != -1) {
+                       continue;
+                }
+                 if ((()) != -1) {                 
+                 		defaultMatch = ;
+                  	setLauncher[0] = new ComponentName(, );
+                } else {
+                       setLauncher[1] = new ComponentName(, );
+                 }
+            }
+            (TAG, "defaultMatch = " + defaultMatch);
+
+            try {
+                (filter, defaultMatch, setLauncher, launcher, getCurrentUserIdLocked());
+            } catch (RemoteException e) {
+                throw new RuntimeException("Package manager has died", e);
+            }
+        }
+    }
+ 
+    private boolean hasApkInstalled(String packageName) {
+        if (packageName == null || "".equals(packageName)) {
+                       return false;
+               }
+         info = null;
+        try {
+            info = ().getApplicationInfo(packageName, 0);
+           (TAG, "packageName found " + info);
+            return info != null;
+        } catch (NameNotFoundException e) {
+           (TAG, "packageName not found " + packageName + " " + e);
+            return false;
+        }
+    }
+    //end
+
     boolean startHomeActivityLocked(int userId, String reason) {
-        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
+         setDefaultLauncher(userId);

遇到的坑

  • String className = “”;
    此处的className要是完整的名字,不能是.MainActivity,否则PackageManagerService会打印
Removing dangling preferred activity:xxxxxxx 

将我们原本设置的preferred activity删除掉。

  • queryIntentActivities
    此处query出来的launcher的activities,有多个launcher,与PackageManagerService当中识别到的launcher数量不一致,导致打印:
Result set changed, dropping preferred activity for xxxx

同样会删除我们之前设置的preferred activity.
所以采用了恶心的代码,删除掉其他多的activity,与PackageManagerService保持一致

参考网页

/lancelots/article/details/82985971