默认Launcher
文章目录
1. 简介
1.1 Launcher启动流程
当系统启动Launcher的时候会在ActivityManagerService中去获取Launcher的activity的信息,然后再调用startActivity。在没有设定默认的Launcher,在获取启动Launcher的Intent的时候会进行弹窗选择,弹窗如图1

选择always后会在将对应的Launcher包名存储成首选项。
1.2 Launcher发生崩溃
当应用发生崩溃时,ActivityManagerService会进行监测,监测到发生崩溃会,就会进行一系列的处理,如打印日志,弹出崩溃弹窗(如图2)等

在Launcher第一次发生崩溃时AMS就会清除发生Launcher存储的首选项,默认应用数据存储到首选项里的,发生崩溃这时候重启手机就会弹窗图1弹窗选择默认Launcher。
1.3 选择默认应用
Android Q开始,新增 RoleManager、RoleManagerService 等类,通过 RoleManager 设置默认应用取代通过PackageManagerService里添加首选项方式。
具体操作在packages/apps/PermissionController/里,在Settings里设置默认应用就是动态添加PermissionController里的Preference来实现的。
2. 实现当其中一个Launcher发生崩溃自动切换默认Launcher
2.1 目前想法
2.1.1 修改方案
在AMS监测应用发生崩溃处理的地方实现切换默认Launcher
//services/core/java/com/android/server/am/ActivityManagerService.java#handleApplicationCrashInner()
if (processName.equals("com.zwh.simplelauncher")){
RoleManager roleManager = (RoleManager)mContext.getSystemService(RoleManager.class);
Consumer<Boolean> callback = successful -> {
if (successful) {
android.util.Log.i("simplelauncher", "handleApplicationCrashInner: successful");
} else {
android.util.Log.i("simplelauncher", "handleApplicationCrashInner: error");
}
};
roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, "com.android.Launcher3", r.userId, Process.myUserHandle(), mContext.getMainExecutor(),callback);
}
能够到达效果,并且在重启后不会切换到发生崩溃的Launcher,只能通过Settings里的开关去切换
2.1.2 存在缺陷
- 目前使用RoleManager去切换默认应用时需要系统权限,应用三方Launcher无法通过该方式去实现,目前我实现方式是如下,通过去除权限监测部分
//system\packages\modules\Permission\service\java\com\android\role\RoleService.java#addRoleHolderAsUser
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
@NonNull RemoteCallback callback) {
......
// getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
// "addRoleHolderAsUser");
......
}
- 由于处理应用发生crash的时候会检查是否发生频繁crash(两次crash时间段很短),频繁crash就会弹出应用崩溃弹窗(如图2),这时候Launcher进程也会从新启动,也就会从新弹出Launcher默认选择框,因此还需要处理弹窗部分。
2.2 更新修改地点
2.2.1 修改方案
修改思想:在进行弹窗的时候进行切换Launcher,这个时候可以进行隐藏崩溃弹窗。弹窗在第一次出现crash的时候不会弹窗,会频繁出现crash的时候弹出(也就是一分钟内出现两次crash)
修改代码:
- 过滤清楚默认Launcher配置(原因可以看3.2)
if (proc.isHomeProcess() && proc.hasActivities() && (app.info.flags & FLAG_SYSTEM) == 0&&app.processName.equals("com.zwh.SimpleLauncher")) {
proc.clearPackagePreferredForHomeActivities();
}
- AppErrors#handleShowAppErrorUi
if (proc.processName.equals("com.zwh.simplelauncher")){
RoleManager roleManager = (RoleManager)mContext.getSystemService(RoleManager.class);
Consumer<Boolean> callback = successful -> {
if (successful) {
android.util.Log.i("simplelauncher", "handleShowAppErrorUi: successful");
} else {
android.util.Log.i("simplelauncher", "handleShowAppErrorUi: error");
}
};
roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, proc.processName, proc.userId, Process.myUserHandle(), mContext.getMainExecutor(),callback)

5254

被折叠的 条评论
为什么被折叠?



