Android10 设置默认Launcher

时间:2025-01-27 14:03:02
  1. 不保留系统launcher
    在mk文件中添加这个属性LOCAL_OVERRIDES_PACKAGES := Launcher3 对应的mk中删除,不让其编译即可。
  2. 保留系统默认的Launcher

当系统存在多个launcher时,若没有设置默认launcher,开机启动后会弹出提示框,罗列所有launcher,用户选择并设置了默认launcher后,按home键以及以后重启都会进入默认的launcher。亦或者在设置--》应用和通知--》默认应用--》主屏幕应用 中也可设置默认launcher。

客户希望系统能直接就进入我设定的launcher而不是弹出框后选择然后设置

前提:客户的app需要有home属性

<intent-filter>
    <action android:name="" />
    <category android:name=""/>
    <category android:name=""/>
    <category android:name="" />
</intent-filter>

修改方法:

首先我们需要增加全局属性.DEFAULT_LAUNCHER,,客户可通过修改该属性设置自定义桌面

1:增加自定义属性:
//frameworks\base\core\java\android\provider\
  public static final class Global extends NameValueTable {
        public static final String DEFAULT_LAUNCHER = "my_default_launcher";
  }

public static final class System extends NameValueTable {
     public static final String DEFAULT_LAUNCHER = Global.DEFAULT_LAUNCHER;
     PUBLIC_SETTINGS.add(DEFAULT_LAUNCHER);
     MOVED_TO_GLOBAL.add(.DEFAULT_LAUNCHER);
     
}
frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\
 private void loadGlobalSettings(SQLiteDatabase db) {
      loadStringSetting(stmt, .DEFAULT_LAUNCHER,
                    .default_launcher);
 }               
//frameworks\base\packages\SettingsProvider\res\values\
<string name="default_launcher" translatable="false">.launcher3/.</string>

两种方法可选:

  • 修改弹出框界面直接设置launcher,弹出提示框界面是:frameworks/base/core/java/com/android/internal/app/:修改方法:在configureContentView内直接读取自定义的桌面,然后替代launcher3

1:frameworks/base/core/java/com/android/internal/app/ 的configureContentView 读取设置的默认桌面,进行设置,mResolvingHome就是表示需要选择的是不是home
在这里只针对home作处理。
public boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
        List<ResolveInfo> rList) {
  //....
    if (rebuildCompleted) {
        //....
        //phoebe add for default launcher for prop .DEFAULT_LAUNCHER
        if(mResolvingHome){
               String defaultlauncher = (getContentResolver(), .DEFAULT_LAUNCHER);
        final TargetInfo defaultTarget = (defaultlauncher);
        (TAG, "zmm add for configureContentView:defaultlauncher:" + defaultlauncher + ":" + defaultTarget);
        if (defaultTarget != null) {
            safelyStartActivity(defaultTarget);
            ();
            mRegistered = false;
            finish();
            return true;
        }     
        }
        
    }
}
2:在ResolveListAdapter 增加targetInfoForDefault方法,并且在rebuildList成功以后,再次设置默认laucnher
    public class ResolveListAdapter extends BaseAdapter {
        @Nullable
public TargetInfo targetInfoForDefault(String info) {
    if ((info)) {
        return null;
    }
    ///
    String[] namesArray = ().split("/");
    if (namesArray == null ||  < 2) {
        return null;
    }
    String packageName = namesArray[0];
    String activityInfo = namesArray[1];
    if ((packageName) || (activityInfo)) {
        return null;
    }
    ComponentName componentName = new ComponentName((), ());
    (TAG, "zmm add for targetInfoForDefault:" + componentName + ":" + ());

    for (TargetInfo targetInfo : mDisplayList) {
        ComponentName targetComponentName = ();
        if ((targetComponentName)) {
            return targetInfo;
        }
    }
    return null;
}    

private void postListReadyRunnable() {
    if (mPostListReadyRunnable == null) {
        mPostListReadyRunnable = new Runnable() {
            @Override
            public void run() {
                //phoebe add for default launcher for prop .DEFAULT_LAUNCHER
               String defaultlauncher = mResolvingHome ? ((), .DEFAULT_LAUNCHER) : null;
                final TargetInfo defaultTarget = (defaultlauncher) ? null : (defaultlauncher);
                (TAG, "zmm add for postListReadyRunnable defaultlauncher:" + defaultlauncher + ":" + defaultTarget);
                if (defaultTarget != null) {
                    safelyStartActivity(defaultTarget);
                    finish();
                    return;
                }
                setHeader();
                resetButtonBar();
                onListRebuilt();
                mPostListReadyRunnable = null;
            }
        };
        getMainThreadHandler().post(mPostListReadyRunnable);
    }
}
}    

修改ActivityManagerService 跳过ResolverActivity

1:ActivityStartController 的startHomeActivity方法内读取用户设置的桌面,并且跳过Settings,和Provision
因为第一次开机,会先Settings的CryptKeeper(加密),FallbackHome(设备正在启动中)接着是provision 的默认桌面,再是launcher3的Launcher页面
zmm add for startHomeActivity...:ComponentInfo{/}
   zmm add for startHomeActivity...:ComponentInfo{/}
   zmm add for startHomeActivity...:ComponentInfo{/}
    zmm add for startHomeActivity....:ComponentInfo{.launcher3/.}
//frameworks/base/services/core/java/com/android/server/wm/
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
        final ActivityOptions options = ();
        (WINDOWING_MODE_FULLSCREEN);
        if (!()) {
            // The resolver activity shouldn't be put in home stack because when the foreground is
            // standard type activity, the resolver activity should be put on the top of current
            // foreground instead of bring home stack to front.
            (ACTIVITY_TYPE_HOME);
        }
        //phoebe add for default launcher for prop .DEFAULT_LAUNCHER skip settings,Provision
        String shortName = (intent == null || () == null) ? null : ().getPackageName();
        if (!isSettingsApp(shortName) && !isProvisionApp(shortName) && setTargetActivityAsPreferredActivity()) {
            //(TAG, " zmm add for  startHomeActivity as user seetings..");
            return;
        }
         //phoebe add for default launcher for prop .DEFAULT_LAUNCHER skip settings,Provision end
       ...
    }

//判断是不是Settings app
    private boolean isSettingsApp(String shortName) {
        return shortName != null && ("");
    }

//判断是不是Provision app
    private boolean isProvisionApp(String shortName) {
        return shortName != null && ("");
    }
//设置用户设置的桌面
    private boolean setTargetActivityAsPreferredActivity() {

        boolean result = false;
        Context context = ;
        if (context == null)
            return result;
        String info = ((), .DEFAULT_LAUNCHER);
        (TAG, " zmm add for  setTargetActivityAsPreferredActivity info=" + info);
        if ((info)) {
            return result;
        }
        String[] namesArray = ("/");
        if (namesArray == null ||  < 2) {
            return result;
        }
        String packageName = namesArray[0];
        String activityInfo = namesArray[1];
        if ((packageName) || (activityInfo)) {
            return result;
        }
        IntentFilter filter = new IntentFilter();
        ("");
        ("");
        ("");

        Intent intent = new Intent(Intent.ACTION_MAIN);
        (Intent.CATEGORY_HOME);

        packageName = ();
        activityInfo = ();
        PackageManager pm = ();
        List<ResolveInfo> list = (intent, 0);
        final int N = list == null ? 0 : ();
        ComponentName[] set = new ComponentName[N];
        ComponentName componentName = null;
        int bestMatch = 0;
        for (int i = 0; i < N; i++) {
            ResolveInfo r = (i);
            set[i] = new ComponentName(, );
            if ( > bestMatch) bestMatch = ;
            if (() && ()) { /*modify target apk packageName  填写你的包名*/
                componentName = set[i];
            }
        }

//        (TAG, "zmm add for setTargetActivityAsPreferredActivity newcomponentName=" + componentName);
        if (null != componentName) {
            (filter, IntentFilter.MATCH_CATEGORY_EMPTY, set, componentName);
            (Intent.FLAG_ACTIVITY_NEW_TASK);
            (intent);
            result = true;
        }

        return result;
    }
2:接着修改frameworks/base/services/core/java/com/android/server/pm/,需要把用户在设置--》默认应用中选择的桌面应用保存到自定义的属性中。
ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
            int userId) {
      ...
        for (int i = 0; i < resolveInfosSize; i++) {
            ResolveInfo resolveInfo = (i);

            if ( != null && (
                    , packageName)) {
                        //phoebe add start
                ComponentName componentName = new ComponentName(,
                        );
                (TAG, "zmm add for getHomeActivitiesAsUser:com:"+componentName);
                String value =  + "/" + ;
                ((),
                        .DEFAULT_LAUNCHER, value);
                        //phoebe add end
                return componentName;
            }
        }
        return null;
    }

以上两种都可实现根据用户配置切换默认launcher

1:adb  切换
adb shell settings put global my_default_launcher .launcher3/.
2:app可如此调用:
(getContentResolver(), "my_default_launcher", "/");

客户的app如果是普通的三方app,设置Global属性可能是报错没有权限:

(getContentResolver(), "my_default_launcher", "/");
报错:缺少权限:.WRITE_SECURE_SETTINGS
该权限是系统app才能申请的权限,普通app申请不到的话,我们可以去掉该限制。
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/ 
@@ -1249,18 +1250,23 @@ public class SettingsProvider extends ContentProvider {
     private boolean mutateGlobalSetting(String name, String value, String tag,
             boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
             int mode) {
-        // Make sure the caller can change the settings - treated as secure.
 -       enforceWritePermission(.WRITE_SECURE_SETTINGS);
         
       
         String pkg = ""; //数据写入时使用系统settings应用的包名,系统会进行调用进程的包名判断
         if(!"my_default_launcher".equals(name)){  //phoebe add 自定义数据不进行权限验证
              pkg = "";
              // Make sure the caller can change the settings - treated as secure.
              enforceWritePermission(.WRITE_SECURE_SETTINGS);
            }

//下面修改在插入操作时使用上面预设的包名,绕过包名验证
@@ -1268,7 +1274,7 @@ public class SettingsProvider extends ContentProvider {
                 case MUTATION_OPERATION_INSERT: {
                     return (SETTINGS_TYPE_GLOBAL,
                             UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
+                            "".equals(pkg)?getCallingPackage():pkg, forceNotify,  CRITICAL_GLOBAL_SETTINGS);
                 }

每日语录:滴水穿石!!!加油!!!

单曲循环《如愿》