问题
机器装有多个launcher,第一次开机,系统会弹出让用户选择哪个作为默认launcher的对话框,但是客户不希望看到这个框,默认使用其中的一个launcher
涉及代码
frameworks/base/services/core/java/com/android/server/am/
frameworks/base/services/core/java/com/android/server/pm/
修改方法
在ActivityManagerService中的startHomeActivityLocked之前,将客户希望的launcher设置到系统的addPreferredActivity(mPreferredActivities)当中,对应的xml配置文件在/data/system/users/0/ 当中,例如
<preferred-activities>
<item name="/.MainActivity" match="100000" always="true" set="2">
<set name="/.MainActivity" />
<set name=".launcher3/.Launcher" />
<filter>
<action name="" />
<cat name="" />
<cat name="" />
</filter>
</item>
</preferred-activities>
修改方法
svn diff
+ //if no preferered launcher activity exist, set the default one
+ private void setDefaultLauncher(int userId) {
+ // get default component
+ String packageName = "";
+ String className = "";
+ IPackageManager pm = ();
+ //判断指定的launcher是否存在
+ (TAG, "setDefaultLauncher packageName " + packageName + " className " + className);
+ if (hasApkInstalled(packageName)) {
+ (TAG, "default packageName = " + packageName + ", default className = " + className);
+ ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>();
+ ArrayList<ComponentName> cnList = new ArrayList<ComponentName>();
+ ().getPreferredActivities(intentList, cnList, null);
+ IntentFilter dhIF = null;
+ for (int i = 0; i < (); i++) {
+ dhIF = (i);
+ if ((Intent.ACTION_MAIN) && (Intent.CATEGORY_HOME)) {
+ (TAG, "default launcher exist = " + (i).getPackageName());
+ return;
+ }
+ }
+ //获取所有launcher activity
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ (Intent.CATEGORY_HOME);
+ (Intent.CATEGORY_DEFAULT);
+ List<ResolveInfo> list = new ArrayList<ResolveInfo>();
+ try {
+ list = (intent,
+ (()),
+ STOCK_PM_FLAGS, userId);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ // get all components and the best match
+ IntentFilter filter = new IntentFilter();
+ (Intent.ACTION_MAIN);
+ (Intent.CATEGORY_HOME);
+ (Intent.CATEGORY_DEFAULT);
+ final int N = ();
+ //设置默认launcher
+ ComponentName launcher = new ComponentName(packageName, className);
+ ComponentName[] set = new ComponentName[N];
+ ComponentName[] setLauncher = new ComponentName[2];
+ int defaultMatch = 0;
+ for (int i = 0; i < N; i++) {
+ ResolveInfo r = (i);
+ set[i] = new ComponentName(, );
+ (TAG, "======= " + );
+ (TAG, "========= " + );
+ //if (().equals()) {
+ if(("") != -1) {
+ continue;
+ }
+
+ if(("") != -1) {
+ continue;
+ }
+ if ((()) != -1) {
+ defaultMatch = ;
+ setLauncher[0] = new ComponentName(, );
+ } else {
+ setLauncher[1] = new ComponentName(, );
+ }
+ }
+ (TAG, "defaultMatch = " + defaultMatch);
+
+ try {
+ (filter, defaultMatch, setLauncher, launcher, getCurrentUserIdLocked());
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+ }
+
+ private boolean hasApkInstalled(String packageName) {
+ if (packageName == null || "".equals(packageName)) {
+ return false;
+ }
+ info = null;
+ try {
+ info = ().getApplicationInfo(packageName, 0);
+ (TAG, "packageName found " + info);
+ return info != null;
+ } catch (NameNotFoundException e) {
+ (TAG, "packageName not found " + packageName + " " + e);
+ return false;
+ }
+ }
+ //end
+
boolean startHomeActivityLocked(int userId, String reason) {
- if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
+ setDefaultLauncher(userId);
遇到的坑
- String className = “”;
此处的className要是完整的名字,不能是.MainActivity,否则PackageManagerService会打印
Removing dangling preferred activity:xxxxxxx
将我们原本设置的preferred activity删除掉。
- queryIntentActivities
此处query出来的launcher的activities,有多个launcher,与PackageManagerService当中识别到的launcher数量不一致,导致打印:
Result set changed, dropping preferred activity for xxxx
同样会删除我们之前设置的preferred activity.
所以采用了恶心的代码,删除掉其他多的activity,与PackageManagerService保持一致
参考网页
/lancelots/article/details/82985971