系统的选择弹窗是:
frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
///......
if (alwaysCheck) {
final int userId = getUserId();
final PackageManager pm = getPackageManager();
android.util.Log.e("XShawn, "+TAG, "filter="+filter); // android.content.IntentFilter@3544861
for(int i = 0 ; i < filter.countActions(); i++){
android.util.Log.e("XShawn, "+TAG, "filter.getAction["+i+"]="+filter.getAction(i));
}
for(int i = 0 ; i < filter.countCategories(); i++){
android.util.Log.e("XShawn, "+TAG, "filter.getCategory["+i+"]="+filter.getCategory(i));
}
android.util.Log.e("XShawn, "+TAG, "bestMatch="+bestMatch); // 1081344
android.util.Log.e("XShawn, "+TAG, "set="+set); // [Landroid.content.ComponentName;@4f68f86
android.util.Log.e("XShawn, "+TAG, "getComponent="+intent.getComponent()); // com.ordissimo.android.tablet.launcher/com.ordissimo.android.tablet.launcher.home.HomeActivity
// Set the preferred Activity
pm.addPreferredActivity(filter, bestMatch, set, intent.getComponent());
if (ri.handleAllWebDataURI) {
// Set default Browser if needed
final String packageName = pm.getDefaultBrowserPackageNameAsUser(userId);
if (TextUtils.isEmpty(packageName)) {
pm.setDefaultBrowserPackageNameAsUser(ri.activityInfo.packageName, userId);
}
}
} else {
try {
mMultiProfilePagerAdapter.getActiveListAdapter()
.mResolverListController.setLastChosen(intent, filter, bestMatch);
} catch (RemoteException re) {
Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
}
}
///......
}
这里适合打印系统处理时产生的各种参数,进而拿到设置默认Launcher的关键参数。
尝试在SystemServer中 startSystemUI之后设置默认launcher,但首次开机时设置不上,可能是开机向导还没走完,系统没有初始化完的原因。
尝试在SystemServer中startOtherService之前设置,也不太理想。
设置默认Launcher,设置方法可参考PackageManagerService.setHomeActivity方法。
采用监听开机广播的方式处理:
MtkSettings\src\com\emdoor\customization\PreferredActivityReceiver.java
/*
* ****** Copyright © 2015-2022 XShawn ********
* Q Q:930226956 (请备注您的信息)
* 邮箱:shawn.xiafei@foxmail.com
* 语雀:https://www.yuque.com/xshawn
* 更新:2022-03-31 10:21
* ********** All Rights Reserved. ************
*/
package com.emdoor.customization;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class PreferredActivityReceiver extends BroadcastReceiver {
private static final String TAG = "XShawn, PreferredActivityReceiver";
private static final String KEY_ORDISSIMO_SUPPORT = "ro.com.ordissimo.support";
private static final String KEY_ORDISSIMO_INIT = "ordissimo_init";
@Override
public void onReceive(Context context, Intent intent) {
Log.w(TAG, "action: " + intent.getAction());
if (SystemProperties.getBoolean(KEY_ORDISSIMO_SUPPORT, false)) {
setDefaultHome(context);
}
}
private static void setDefaultHome(Context context) {
if (isOrdissimoInit(context)) {
Log.w(TAG, "default home has already been set.");
return;
}
Log.w(TAG, "try to set default home...");
// target activity
final ComponentName targetHome = new ComponentName(
"com.ordissimo.android.tablet.launcher",
"com.ordissimo.android.tablet.launcher.home.HomeActivity"
);
final PackageManager pm = context.getPackageManager();
List<ResolveInfo> homeActivities = new ArrayList<>();
ComponentName currentHome = pm.getHomeActivities(homeActivities);
// pre-check status
if (targetHome.equals(currentHome)) {
Log.w(TAG, "default home has already been set.");
setOrdissimoInit(context, true);
return;
}
// available set
ComponentName[] set = homeActivities.parallelStream()
.map(resolveInfo -> resolveInfo.activityInfo.getComponentName())
.toArray(ComponentName[]::new);
// set default home
context.getPackageManager().replacePreferredActivity(
getHomeFilter(),
IntentFilter.MATCH_CATEGORY_EMPTY,
set,
targetHome
);
// after-check status.
currentHome = pm.getHomeActivities(homeActivities);
if (targetHome.equals(currentHome)) {
Log.w(TAG, "set default home success.");
setOrdissimoInit(context, true);
}
}
private static IntentFilter getHomeFilter() {
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);
return filter;
}
private static boolean isOrdissimoInit(Context context) {
return Settings.Global.getInt(context.getContentResolver(), KEY_ORDISSIMO_INIT, 0) == 1;
}
private static void setOrdissimoInit(Context context, boolean done) {
Settings.Global.putInt(context.getContentResolver(), KEY_ORDISSIMO_INIT, done ? 1 : 0);
}
}
注册广播接收器:
<!-- START. For Ordissimo-Customization. By XShawn@20220331. -->
<receiver
android:name="com.emdoor.customization.PreferredActivityReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<!-- END. For Ordissimo-Customization. By XShawn@20220331. -->
但开机广播是有延时性的,在有开机向导的前提下,能够成功设置默认launcher。
若没有开机向导,开机后直接就进了launcher,此时开机广播还没有发出来,所以默认不成功。
优化方案
找到安装APP的位置,安装完成,主动发广播去修改默认launcher,但这样每次安装都会自动默认上。
//frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
try {
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, null, res, user);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
prepareAppDataAfterInstallLIF(newPackage);
//------------------------
if (pkgName.equals("com.dianxinos.dxhome")){
//发送广播
Intent intent = new Intent("emdoor.intent.action.UPDATE_LANUCHER_APPS");
mContext.sendBroadcast(intent);
}
//------------------------
} else {
// Remove package from internal structures, but keep around any
// data that might have already existed
deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}