有些时候系统里预装了两个电话、桌面这样的应用,开机启动后系统会弹框让你选择使用那一个。
在系统设置中应用和通知里发现有默认应用选项,点进去发现是在 PermissionController 中
默认列表界面
adb shell dumpsys window | findstr mCurrentFocus
mCurrentFocus=Window{ffb6aca u0 com.android.permissioncontroller/com.android.packageinstaller.role.ui.DefaultAppListActivity}
默认应用详情界面
adb shell dumpsys window | findstr mCurrentFocus
mCurrentFocus=Window{d2fceb3 u0 com.android.permissioncontroller/com.android.packageinstaller.role.ui.DefaultAppActivity}
点击 Preference 切换是最终调用的代码走到 setRoleHolderAsUser()
vendor\mediatek\proprietary\packages\apps\PermissionController\src\com\android\packageinstaller\role\ui\ManageRoleHolderStateLiveData.java
public void setRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, boolean add, int flags, @NonNull UserHandle user, @NonNull Context context) { if (getValue() != STATE_IDLE) { Log.e(LOG_TAG, "Already (tried) managing role holders, requested role: " + roleName + ", requested package: " + packageName); return; } if (DEBUG) { Log.i(LOG_TAG, (add ? "Adding" : "Removing") + " package as role holder, role: " + roleName + ", package: " + packageName); } mLastPackageName = packageName; mLastAdd = add; mLastFlags = flags; mLastUser = user; setValue(STATE_WORKING); RoleManager roleManager = context.getSystemService(RoleManager.class); Executor executor = context.getMainExecutor(); Consumer<Boolean> callback = successful -> { if (successful) { if (DEBUG) { Log.i(LOG_TAG, "Package " + (add ? "added" : "removed") + " as role holder, role: " + roleName + ", package: " + packageName); } setValue(STATE_SUCCESS); } else { if (DEBUG) { Log.i(LOG_TAG, "Failed to " + (add ? "add" : "remove") + " package as role holder, role: " + roleName + ", package: " + packageName); } setValue(STATE_FAILURE); } }; if (add) { roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback); } else { roleManager.removeRoleHolderAsUser(roleName, packageName, flags, user, executor, callback); } }
核心方法就是这个,那我们就可以仿照它来了,在 PermissionController 中监听开机广播,直接调用改方法设置默认应用就好。
各默认应用对应的 roleName 如下,改造一下 setRoleHolderAsUser(),传递 roleName 和 packageName
电话
role: android.app.role.DIALER, package: com.android.dialer
短信
role: android.app.role.SMS, package: com.android.mms
主屏幕
role: android.app.role.HOME, package: com.android.launcher3
浏览器
role: android.app.role.BROWSER, package: com.android.browser
vendor\mediatek\proprietary\packages\apps\PermissionController\AndroidManifest.xml
<receiver android:name="com.android.packageinstaller.TemporaryFileManager" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
vendor\mediatek\proprietary\packages\apps\PermissionController\src\com\android\packageinstaller\TemporaryFileManager.java
package com.android.packageinstaller; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.SystemClock; import android.util.Log; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import com.android.packageinstaller.permission.model.AppPermissionGroup; import com.android.packageinstaller.permission.model.AppPermissions; import com.android.packageinstaller.permission.model.Permission; import com.android.packageinstaller.permission.utils.ArrayUtils; import com.android.packageinstaller.permission.utils.Utils; import java.util.List; import java.io.File; import java.io.IOException; import android.app.role.RoleManager; import android.os.UserHandle; import android.os.Process; import java.util.concurrent.Executor; import java.util.function.Consumer; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; /** * Manages files of the package installer and resets state during boot. */ public class TemporaryFileManager extends BroadcastReceiver { private static final String LOG_TAG = TemporaryFileManager.class.getSimpleName(); private void setBootFlag(Context context, int flag){ SharedPreferences sharedPreferences = context.getSharedPreferences("boot_CONFIG", Context.MODE_PRIVATE); Editor editor = sharedPreferences.edit(); editor.putInt("boot_flag", flag).commit(); } private boolean isFirstBoot(Context context){ SharedPreferences sharedPreferences = context.getSharedPreferences("boot_CONFIG", Context.MODE_PRIVATE); return sharedPreferences.getInt("boot_flag", 0) == 0; } @Override public void onReceive(Context context, Intent intent) { Log.e("permission", "action==="+ intent.getAction()); if (isFirstBoot(context)) { setRoleHolderAsUser(context, "com.android.dialer"); setBootFlag(context, 1); } long systemBootTime = System.currentTimeMillis() - SystemClock.elapsedRealtime(); File[] filesOnBoot = context.getNoBackupFilesDir().listFiles(); if (filesOnBoot == null) { return; } for (int i = 0; i < filesOnBoot.length; i++) { File fileOnBoot = filesOnBoot[i]; if (systemBootTime > fileOnBoot.lastModified()) { boolean wasDeleted = fileOnBoot.delete(); if (!wasDeleted) { Log.w(LOG_TAG, "Could not delete " + fileOnBoot.getName() + " onBoot"); } } else { Log.w(LOG_TAG, fileOnBoot.getName() + " was created before onBoot broadcast was " + "received"); } } } public void setRoleHolderAsUser(Context context, String packageName) { String roleName = "android.app.role.DIALER"; boolean add = true; int flags = 0; UserHandle user = Process.myUserHandle(); Log.i("permission", (add ? "Adding" : "Removing") + " package as role holder, role: " + roleName + ", package: " + packageName); RoleManager roleManager = context.getSystemService(RoleManager.class); Executor executor = context.getMainExecutor(); Consumer<Boolean> callback = successful -> { if (successful) { Log.d("permission", "Package " + (add ? "added" : "removed") + " as role holder, role: " + roleName + ", package: " + packageName); } else { Log.d("permission", "Failed to " + (add ? "add" : "remove") + " package as role holder, role: " + roleName + ", package: " + packageName); } }; roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback); Log.i("permission", "addRoleHolderAsUser done"); } }