用户有动态设置launcher的需求。
网上有各种五花八门的方法,复杂,好像也不是都起作用。
我这边实测下来,有一个很简单的方法就可以实现。
先上结论:
需要修改的文件为 frameworks\base\services\core\java\com\android\server\am ActivityManagerService.java
修改函数getHomeIntent如下:
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
//修改设置的Component
//intent.setComponent(mTopComponent);
intent.setComponent(getDefaultActivity());
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
可以看到,实际上只修改了一行代码,将intent.setComponent()的参数由mTopComponent替换为我们指定的default Activity。这样其实已经大功告成了。
但是,如何知道我们默认package的启动Activity呢, 所以添加了getDefaultActivity()这个函数,作用是根据package name 获得启动activity的名称:
private ComponentName getDefaultActivity() { ComponentName defComp = null; // 默认启动的apk,可以修改为任意包名。 // 也可以修改为通过property或settings动态设置 String pkgDef = "com.android.launcher"; Slog.i(TAG, "defautl packageName = " + pkgDef); Intent launcherIntent = new Intent("android.intent.action.MAIN", null); launcherIntent.setPackage(pkgDef); List<ResolveInfo> localResolveInfo = mContext.getPackageManager().queryIntentActivities(launcherIntent, 0); if (!localResolveInfo.isEmpty()) { ActivityInfo activityInfo = localResolveInfo.get(0).activityInfo; if (activityInfo != null) { Log.d(TAG, "get default activity" + activityInfo.name); defComp = new ComponentName(pkgDef, activityInfo.name); } } return defComp; }
编译,测试,已经起作用了。
下面解释下为什么要这么改:
在函数startHomeActivityLocked中,如下两行代码决定默认启动的Activity:Intent intent = getHomeIntent(); ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
跟踪到resolveActivityInfo这个函数
private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) { ActivityInfo ai = null; //下面的逻辑和此处获得的ComponentName有关 ComponentName comp = intent.getComponent(); try { if (comp != null) { // Factory test. ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); } else {
这个函数的逻辑是:如果intent.getComponent()为空,就会返回ResolverActivity,也就是装了多个launcher时,开机时弹出的选择框。
而默认的intent.getComponent返回的Component其实是getHomeIntent里设置的mTopComponent,搜索上下代码可以发现mTopComponent=NULL。所以默认会弹出选择框。
既然这样,要想不弹出选择框,而是直接进入默认应用,需要在intent.getComponent()返回我们需要的ComponentName。
也就是说在getHomeIntent()返回的Intent中,包含我们要启动的ComponentName。
故,修改getHomeIntent(),将mTopComponent替换为我们想启动的Activity。