Android 源码多个Launcher设置默认Launcher

打印 上一主题 下一主题

主题 1012|帖子 1012|积分 3036

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录
第一部分、android10之前
一.多个launcher 启动设置默认launcher的核心类
二 在自定义服务里面设置默认Launcher
第二部分、android10之后
一、Launcher应用内置并设置为默认Launcher
1.通过ResolverActivity.java设置为默认Launcher
  改法一:
改法二:
2.通过ActivityManagerService.java设置为默认Launcher主要修改getHomeIntent(),将其替换成必要默认的Launcher即可。
改法一(常规):
改法二(简化):
二、普通应用内置并设置为默认Launcher
1.欺压替换
2.添加属性
Android11之前的

在Android系统中,设置默认Launcher(启动器)是一个涉及系统权限和配置的过程。通常,这个过程不是通过简单地修改几个文件或设置就能完成的,由于它必要系统级别的权限。不过,我可以概述一下在Android源码级别如何设置或答应用户选择默认Launcher的大抵步调。
第一部分、android10之前

一.多个launcher 启动设置默认launcher的核心类

代码路径:frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
2.多个launcher 启动设置默认launcher的核心功能实现和分析
通过在系统中内置其他Launcher时,在系统进入启动Launcher的过程中,会在ResolverActivity.java中,首先查询系统中由几个Launcher,当有多个Launcher时,会让用户选择启动的Launcher,然后作为默认启动Launcher. 以是就来分析该怎么设置默认Launcher,而不用用户选择启动Launcher.
先来看下ResolverActivity.java的相关源码
  1. @UiThread
  2.   public class ResolverActivity extends Activity {  
  3.       @Override
  4.       protected void onCreate(Bundle savedInstanceState) {
  5.           // Use a specialized prompt when we're handling the 'Home' app startActivity()
  6.           final Intent intent = makeMyIntent();
  7.           final Set<String> categories = intent.getCategories();
  8.           if (Intent.ACTION_MAIN.equals(intent.getAction())
  9.                   && categories != null
  10.                   && categories.size() == 1
  11.                   && categories.contains(Intent.CATEGORY_HOME)) {
  12.               // Note: this field is not set to true in the compatibility version.
  13.               mResolvingHome = true;
  14.           }
  15.   
  16.           setSafeForwardingMode(true);
  17.   
  18.           onCreate(savedInstanceState, intent, null, 0, null, null, true);
  19.       }
  20.   
  21.       /**
  22.        * Compatibility version for other bundled services that use this overload without
  23.        * a default title resource
  24.        */
  25.       @UnsupportedAppUsage
  26.       protected void onCreate(Bundle savedInstanceState, Intent intent,
  27.               CharSequence title, Intent[] initialIntents,
  28.               List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
  29.           onCreate(savedInstanceState, intent, title, 0, initialIntents, rList,
  30.                   supportsAlwaysUseOption);
  31.       }
  32.   
  33.       protected void onCreate(Bundle savedInstanceState, Intent intent,
  34.               CharSequence title, int defaultTitleRes, Intent[] initialIntents,
  35.               List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
  36.           setTheme(R.style.Theme_DeviceDefault_Resolver);
  37.           super.onCreate(savedInstanceState);
  38.   
  39.           // Determine whether we should show that intent is forwarded
  40.           // from managed profile to owner or other way around.
  41.           setProfileSwitchMessageId(intent.getContentUserHint());
  42.   
  43.           try {
  44.               mLaunchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid(
  45.                       getActivityToken());
  46.           } catch (RemoteException e) {
  47.               mLaunchedFromUid = -1;
  48.           }
  49.   
  50.           if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
  51.               // Gulp!
  52.               finish();
  53.               return;
  54.           }
  55.   
  56.           mPm = getPackageManager();
  57.   
  58.           mPackageMonitor.register(this, getMainLooper(), false);
  59.           mRegistered = true;
  60.           mReferrerPackage = getReferrerPackageName();
  61.   
  62.           final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
  63.           mIconDpi = am.getLauncherLargeIconDensity();
  64.   
  65.           // Add our initial intent as the first item, regardless of what else has already been added.
  66.           mIntents.add(0, new Intent(intent));
  67.           mTitle = title;
  68.           mDefaultTitleResId = defaultTitleRes;
  69.   
  70.           mUseLayoutForBrowsables = getTargetIntent() == null
  71.                   ? false
  72.                   : isHttpSchemeAndViewAction(getTargetIntent());
  73.   
  74.           mSupportsAlwaysUseOption = supportsAlwaysUseOption;
  75.   
  76.           if (configureContentView(mIntents, initialIntents, rList)) {
  77.               return;
  78.           }
  79.   
  80.           final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
  81.           if (rdl != null) {
  82.               rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
  83.                   @Override
  84.                   public void onDismissed() {
  85.                       finish();
  86.                   }
  87.               });
  88.               if (isVoiceInteraction()) {
  89.                   rdl.setCollapsed(false);
  90.               }
  91.   
  92.               rdl.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
  93.                       | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
  94.               rdl.setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
  95.   
  96.               mResolverDrawerLayout = rdl;
  97.           }
  98.   
  99.           mProfileView = findViewById(R.id.profile_button);
  100.           if (mProfileView != null) {
  101.               mProfileView.setOnClickListener(this::onProfileClick);
  102.               bindProfileView();
  103.           }
  104.   
  105.           initSuspendedColorMatrix();
  106.   
  107.           if (isVoiceInteraction()) {
  108.               onSetupVoiceInteraction();
  109.           }
  110.           final Set<String> categories = intent.getCategories();
  111.           MetricsLogger.action(this, mAdapter.hasFilteredItem()
  112.                   ? MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_APP_FEATURED
  113.                   : MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_NONE_FEATURED,
  114.                   intent.getAction() + ":" + intent.getType() + ":"
  115.                           + (categories != null ? Arrays.toString(categories.toArray()) : ""));
  116.       }
复制代码
在ResolverActivity.java中的onCreate中首先读取系统中的Home属性的Launcher列表,然后在
ResolveListAdapter中展示Launcher的列表,以是可以在这些直接设置默认的Launcher,然后finish掉这个页面,直接进入默认Launcher页面
具体修改为:
  1. --- a/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
  2. +++ b/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
  3. @@ -278,9 +278,53 @@ public class ResolverActivity extends Activity {
  4.          intent.setFlags(intent.getFlags()&~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
  5.          return intent;
  6.      }
  7. -
  8. +    private void setDefaultLauncher(String defPackageName,String defClassName) {
  9. +        if ((defPackageName != null && defPackageName.trim().length() > 1) && (defClassName != null && defClassName.trim().length() > 0)) {
  10. +            IntentFilter filter = new IntentFilter();
  11. +            filter.addAction("android.intent.action.MAIN");
  12. +            filter.addCategory("android.intent.category.HOME");
  13. +            filter.addCategory("android.intent.category.DEFAULT");
  14. +
  15. +            Intent intent=new Intent(Intent.ACTION_MAIN);
  16. +            intent.addCategory(Intent.CATEGORY_HOME);
  17. +            List<ResolveInfo> list = new ArrayList<ResolveInfo>();
  18. +            list = getPackageManager().queryIntentActivities(intent, 0);
  19. +            final int N = list.size();
  20. +            ComponentName[] set = new ComponentName[N];
  21. +            int bestMatch = 0;
  22. +            for (int i=0; i<N; i++) {
  23. +                ResolveInfo r = list.get(i);
  24. +                set[i] = new ComponentName(r.activityInfo.packageName,
  25. +                        r.activityInfo.name);
  26. +               if (r.match > bestMatch) bestMatch = r.match;
  27. +            }
  28. +            ComponentName preActivity = new ComponentName(defPackageName, defClassName);
  29. +            getPackageManager().addPreferredActivity(filter, bestMatch, set,preActivity);
  30. +        }
  31. +    }
  32.      @Override
  33.      protected void onCreate(Bundle savedInstanceState) {
  34. +                   boolean firstBoot = (Settings.Global.getInt(getApplication().getContentResolver(),
  35. +                    "default_home_launcher", 0) == 0);
  36. +                       String defPackageName = Settings.Global.getString(getContentResolver(),"launcher_pkgname");
  37. +                       String defClassName = Settings.Global.getString(getContentResolver(),"launcher_classname");
  38. +                       Log.e(TAG,"pkgname:"+defPackageName+"---defClassName:"+defClassName);
  39. +        if(firstBoot &&!TextUtils.isEmpty(defPackageName)){
  40. +                       try {
  41. +              setDefaultLauncher(defPackageName,defClassName);
  42. +                     Intent defIntent = new Intent();
  43. +              defIntent.setClassName(defPackageName, defClassName);
  44. +              defIntent.setAction("android.intent.action.MAIN");
  45. +              defIntent.addCategory("android.intent.category.HOME");
  46. +              defIntent.addCategory("android.intent.category.DEFAULT");
  47. +              startActivity(defIntent);
  48. +              Settings.Global.putInt(getApplication().getContentResolver(),
  49. +                    "default_home_launcher",1);
  50. +              this.finish();
  51. +                       } catch (Exception e) {
  52. +              e.printStackTrace();
  53. +                       }
  54. +        }
  55.          ActivityDebugConfigs.addConfigChangedListener(mDebugConfigListener);
  56.          // Use a specialized prompt when we're handling the 'Home' app startActivity()
  57. @@ -1291,7 +1335,6 @@ public class ResolverActivity extends Activity {
  58.          setContentView(mLayoutId);
复制代码
在onCreate中的增长setDefaultLauncher(String defPackageName,String defClassName)这个设置默认Launcher的方法,而PM的addPreferredActivity设置默认Launcher,就实现了功能
二 在自定义服务里面设置默认Launcher

  1. public class MdmManagerService extends IMdmManager.Stub {
  2.         private static String TAG ="MdmManagerService";
  3.     private Context mContext;
  4.     private Handler mHandler = new Handler(Looper.getMainLooper());
  5.     public MdmManagerService(Context context){
  6.         this.mContext = context;
  7.                 mHandler.postDelayed(mRunnable, 0);
  8.         //IntentFilter mintent=new IntentFilter("com.sprd.settings.action.apistart");
  9.         //mContext.registerReceiver(mBroadcastReceiver,mintent);
  10.     }
  11.     private BroadcastReceiver mBroadcastReceiver =new BroadcastReceiver() {
  12.         @Override
  13.         public void onReceive(Context context, Intent intent) {
  14.             Log.e(TAG,"action");
  15.                         //mHandler.postDelayed(mRunnable, 500);
  16.         }
  17.     };
  18.     private Runnable mRunnable = new Runnable() {
  19.         @Override
  20.         public void run() {
  21.             Log.e(TAG, "actionRun");
  22.             try {
  23.                 //setStatusBarExpandPanelDisabled(true);
  24.                                 String defaultLauncher = SystemProperties.get("persist.sys.ployer.default.launcher", "");
  25.                 if(TextUtils.isEmpty(defaultLauncher)){
  26.                    setDefaultLauncher("com.android.launcher3", "com.android.launcher3.Launcher");
  27.                    //setDefaultLauncher("com.ployer.interfacedemo", "com.ployer.interfacedemo.MainActivity");
  28.                         }
  29.             } catch (Exception e) {
  30.                 e.printStackTrace();
  31.             }
  32.         }
  33.     };
  34.     private void setDefaultApplication(String roleName, String packageName) {
  35.         RoleManager roleManager = mContext.getSystemService(RoleManager.class);
  36.         Executor executor = mContext.getMainExecutor();
  37.         Consumer<Boolean> callback = successful -> {
  38.             if (successful) {
  39.                 Log.e(TAG, "setDefaultApplication packageName:"+packageName+" successful");
  40.             }
  41.         };
  42.         roleManager.addRoleHolderAsUser(roleName, packageName, 0, android.os.Process.myUserHandle(), executor, callback);
  43.     }
  44.     public void setDefaultLauncher(String packageName, String className) throws RemoteException {
  45.        Log.e(TAG, "setDefaultLauncher:packageName="+packageName+"--className:"+className);
  46.        final long ident = Binder.clearCallingIdentity();
  47.        try {
  48.             if (isPkgInstalled(mContext, packageName)) {
  49.                             Settings.Global.putString(mContext.getContentResolver(),"launcher_pkgname",packageName);
  50.                             Settings.Global.putString(mContext.getContentResolver(),"launcher_classname",className);
  51.                 String value = packageName + "/" + className;
  52.                 SystemProperties.set("persist.sys.ployer.default.launcher", value);
  53.                                 setDefaultApplication("android.app.role.HOME",packageName);
  54.             } else {
  55.                 Log.e(TAG, "setDefaultLauncher packageName is not exist");
  56.             }
  57.            } catch (Exception e) {
  58.           e.printStackTrace();
  59.        }finally {
  60.           Binder.restoreCallingIdentity(ident);
  61.        }
  62.     }
  63.     private boolean isPkgInstalled(Context context, String packageName) {
  64.         if (packageName == null || "".equals(packageName))
  65.             return false;
  66.         ApplicationInfo info = null;
  67.         try {
  68.             info = context.getPackageManager().getApplicationInfo(packageName, 0);
  69.             return info != null;
  70.         } catch (Exception e) {
  71.             Log.e(TAG, "apk is not installed packageName:" + packageName);
  72.             return false;
  73.         }
  74.     }
复制代码

第二部分、android10之后

一、Launcher应用内置并设置为默认Launcher

主要使用ResolverActivity.java或ActivityManagerService.java来实现,接下来我将分别举例阐明:
1.通过ResolverActivity.java设置为默认Launcher

    主要是由addPreferredActivity设置默认Launcher实现。
  改法一:

代码路径:frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
以下基于Android11代码:
  1. protected void onCreate(Bundle savedInstanceState, Intent intent,
  2.             CharSequence title, int defaultTitleRes, Intent[] initialIntents,
  3.             List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
  4.         setTheme(appliedThemeResId());
  5.         super.onCreate(savedInstanceState);
  6.         //add
  7.            if(mResolvingHome){
  8.             setDefaultLauncher();
  9.             finish();
  10.             return;
  11.         }
  12.         //add
  13.         ...
  14.         }
  15. private void setDefaultLauncher() {
  16.             try {
  17.                 final PackageManager pm = getPackageManager();
  18.                 String defPackageName = "com.android.launcher3";//默认launcher包名
  19.                 String defClassName = "com.android.searchlauncher.SearchLauncher";//默认launcher类名
  20.                 IntentFilter filter = new IntentFilter();
  21.                 filter.addAction("android.intent.action.MAIN");
  22.                 filter.addCategory("android.intent.category.HOME");
  23.                 filter.addCategory("android.intent.category.DEFAULT");
  24.                 Intent intent = new Intent(Intent.ACTION_MAIN);
  25.                 intent.addCategory(Intent.CATEGORY_HOME);
  26.                 List<ResolveInfo> list = new ArrayList<ResolveInfo>();
  27.                 list = pm.queryIntentActivities(intent, 0);
  28.                 final int N = list.size();
  29.                 ComponentName[] set = new ComponentName[N];
  30.                 int bestMatch = 0;
  31.                 for (int i = 0; i < N; i++) {
  32.                     ResolveInfo r = list.get(i);
  33.                     set[i] = new ComponentName(r.activityInfo.packageName,
  34.                             r.activityInfo.name);
  35.                     if (r.match > bestMatch) bestMatch = r.match;
  36.                 }
  37.                 ComponentName preActivity = new ComponentName(defPackageName, defClassName);
  38.                 pm.addPreferredActivity(filter, bestMatch, set, preActivity);
  39.             } catch (Exception e) {
  40.                 e.printStackTrace();
  41.             }
  42.     }
复制代码
改法二:

代码路径:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
  1. boolean startHomeActivityLocked(int userId, String reason) {
  2.                 setDefaultLauncher();//调用设置默认launcher方法
  3.                 SystemProperties.set("persist.sys.boot.bootcomplete","1");
  4.         if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
  5.                 && mTopAction == null) {
  6.             // We are running in factory test mode, but unable to find
  7.             // the factory test app, so just sit around displaying the
  8.             // error message and don't try to start anything.
  9.             return false;
  10.         }
  11.     ...
  12.     ...
  13. }
  14. private void setDefaultLauncher() {
  15.             boolean mFirstLaunch = true;
  16.             String packageName = "包名";//launcher包名
  17.             String className = "类名";
  18.             if ((packageName != null && packageName.trim().length() > 1) && (className != null && className.trim().length() > 0)) {
  19.                 if(mFirstLaunch){
  20.                     IPackageManager pm = ActivityThread.getPackageManager();
  21.                     ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>();
  22.                     ArrayList<ComponentName> cnList = new ArrayList<ComponentName>();
  23.                     mContext.getPackageManager().getPreferredActivities(intentList, cnList, null);
  24.                     IntentFilter dhIF;
  25.                     for(int i = 0; i < cnList.size(); i++){
  26.                         dhIF = intentList.get(i);
  27.                         if(dhIF.hasAction(Intent.ACTION_MAIN) &&
  28.                                 dhIF.hasCategory(Intent.CATEGORY_HOME)) {
  29.                             mContext.getPackageManager().clearPackagePreferredActivities(cnList.get(i).getPackageName());
  30.                         }
  31.                     }
  32.                     Intent intent = new Intent(Intent.ACTION_MAIN);
  33.                     intent.addCategory(Intent.CATEGORY_HOME);
  34.                     List<ResolveInfo> list = new ArrayList<ResolveInfo>();
  35.                     try {
  36.                         list = pm.queryIntentActivities(intent,
  37.                                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
  38.                                 PackageManager.MATCH_DEFAULT_ONLY,UserHandle.getCallingUserId()).getList(); //add .getList()
  39.                     }catch (RemoteException e) {
  40.                         throw new RuntimeException("Package manager has died", e);
  41.                     }
  42.                     IntentFilter filter = new IntentFilter();
  43.                     filter.addAction(Intent.ACTION_MAIN);
  44.                     filter.addCategory(Intent.CATEGORY_HOME);
  45.                     filter.addCategory(Intent.CATEGORY_DEFAULT);
  46.                     final int N = list.size();
  47.                     ComponentName[] set = new ComponentName[N];
  48.                     int bestMatch = 0;
  49.                     for (int i = 0; i < N; i++)
  50.                     {
  51.                         ResolveInfo r = list.get(i);
  52.                         set[i] = new ComponentName(r.activityInfo.packageName,
  53.                                 r.activityInfo.name);
  54.                         if (r.match > bestMatch) bestMatch = r.match;
  55.                     }
  56.                     ComponentName launcher = new ComponentName(packageName, className);
  57.                     try{
  58.                         pm.addPreferredActivity(filter, bestMatch, set, launcher,UserHandle.getCallingUserId());
  59.                     } catch (RemoteException e) {
  60.                         throw new RuntimeException("Package manager has died", e);
  61.                     }
  62.                 }
  63.             }
  64.         }
复制代码
2.通过ActivityManagerService.java设置为默认Launcher
主要修改getHomeIntent(),将其替换成必要默认的Launcher即可。


代码路径:frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
改法一(常规):

  1. Intent getHomeIntent() {
  2. //add
  3.                 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
  4.         Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
  5.                         String defStartPkg = "你的包名";
  6.                         Intent queryIntent = new Intent();
  7.                         final PackageManager mPm = mContext.getPackageManager();
  8.                         queryIntent.addCategory(Intent.CATEGORY_HOME);///没有home可去掉
  9.                         queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
  10.                         queryIntent.setAction(Intent.ACTION_MAIN);
  11.                         List<ResolveInfo> homeActivities = mPm.queryIntentActivities(queryIntent, 0);
  12.                         if(homeActivities != null) {
  13.                                 int activityNum = homeActivities.size();
  14.                                 ComponentName[] set = new ComponentName[activityNum];
  15.                                 for(int i = 0; i < activityNum; i++){
  16.                                         ResolveInfo info = homeActivities.get(i);
  17.                                         set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
  18.                                         if(defStartPkg.equals(info.activityInfo.packageName)){
  19.                                                 Intent intentaa = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  20.                                                 intentaa.setComponent(set[i]);
  21.                                                 intentaa.addCategory(Intent.CATEGORY_HOME);
  22.                                                 return intentaa;
  23.                                         }
  24.                                 }
  25.                         }
  26. //add
  27.         Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  28.         intent.setComponent(mTopComponent);
  29.         if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
  30.             intent.addCategory(Intent.CATEGORY_HOME);
  31.         }
  32.         return intent;
  33.     }
复制代码
改法二(简化):

  1. Intent getHomeIntent() {
  2.         Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  3.         //add
  4.         //intent.setComponent(mTopComponent);
  5.         intent.setComponent(new ComponentName("包名", "类名"));
  6.         //add
  7.         intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
  8.         if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
  9.             intent.addCategory(Intent.CATEGORY_HOME);
  10.         }
  11.         return intent;
  12.     }
复制代码
二、普通应用内置并设置为默认Launcher

由于这类应用通常没有android.intent.category.HOME这个Category,故无法使用上述常规方式来设置为默认应用,使用必要我们另辟蹊径,这边也是为各位提供两种方法。
1.欺压替换


首先将应用设置为默认开机启动,但由于没有android.intent.category.HOME这个Category以是提供通过ResolverActivity.java设置是不行的,必要通过修改ActivityManagerService.java来实现,只要把改法一中的queryIntent.addCategory(Intent.CATEGORY_HOME);注释掉即可:
  1. Intent getHomeIntent() {
  2. //add
  3.                 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
  4.         Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
  5.                         String defStartPkg = "你的包名";
  6.                         Intent queryIntent = new Intent();
  7.                         final PackageManager mPm = mContext.getPackageManager();
  8.                         //queryIntent.addCategory(Intent.CATEGORY_HOME);///没有home可去掉
  9.                         queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
  10.                         queryIntent.setAction(Intent.ACTION_MAIN);
  11.                         List<ResolveInfo> homeActivities = mPm.queryIntentActivities(queryIntent, 0);
  12.                         if(homeActivities != null) {
  13.                                 int activityNum = homeActivities.size();
  14.                                 ComponentName[] set = new ComponentName[activityNum];
  15.                                 for(int i = 0; i < activityNum; i++){
  16.                                         ResolveInfo info = homeActivities.get(i);
  17.                                         set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
  18.                                         if(defStartPkg.equals(info.activityInfo.packageName)){
  19.                                                 Intent intentaa = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  20.                                                 intentaa.setComponent(set[i]);
  21.                                                 intentaa.addCategory(Intent.CATEGORY_HOME);
  22.                                                 return intentaa;
  23.                                         }
  24.                                 }
  25.                         }
  26. //add
  27.         Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  28.         intent.setComponent(mTopComponent);
  29.         if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
  30.             intent.addCategory(Intent.CATEGORY_HOME);
  31.         }
  32.         return intent;
  33.     }
复制代码
通过上面的修改就可以开机默认启动了,但是会出现按home、recent、back键会退出应用从而进入原生Launcher的情况,以是我们必要对这些按键进行拦截定制:
代码路径:frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
  1. mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
  2.         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
  3. //add
  4.                 ComponentName mHomecom = new ComponentName("包名", "类名");
  5.         mHomeIntent.setComponent(mHomecom);
  6. //add
  7.         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
  8.                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
  9. @Override
  10.     public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
  11. ....
  12. ....
  13. //add
  14. if(keyCode == KeyEvent.KEYCODE_BACK){        if(getClsName(mContext).equals("com.ryanheise.audioservice.AudioServiceFragmentActivity")
  15.                         &&(getInputMethodWindowVisibleHeightLw()==0)){
  16.                         return -1;
  17.                         }
  18.                 }
  19. //add
  20. ....
  21. ....
  22. }
  23. private String getClsName(Context context) {
  24.         try {
  25.              ActivityManager am = context.getSystemService(ActivityManager.class);
  26.              List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
  27.              return tasks.get(0).topActivity.getClassName();
  28.         } catch (Exception e) {
  29.            //ignore
  30.         }
  31.         return "";
  32.     }
复制代码
代码路径:SystemUI\src\com\android\systemui\recents\RecentsActivity.java
  1. import android.content.ComponentName;
  2. Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
  3.          homeIntent.addCategory(Intent.CATEGORY_HOME);
  4.          ComponentName mHomecom = new ComponentName("包名", "类名");
  5.          homeIntent.setComponent(mHomecom);
  6.          homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
  7.                  Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
复制代码
2.添加属性

Android11开始的
android11开始谷歌对pms的分析部分做了一些重构和优化,将一些类和方法从PackageManagerService和PackageParser中分离出来,放到了parsing包和component包下,路径为:frameworks/base/core/java/android/content/pm/
以是我们要修改的文件为frameworks/base/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
  1.       @NonNull
  2.       private static ParseResult<ParsedActivity> parseActivityOrAlias(ParsedActivity activity,
  3.               ParsingPackage pkg, String tag, XmlResourceParser parser, Resources resources,
  4.               TypedArray array, boolean isReceiver, boolean isAlias, boolean visibleToEphemeral,
  5.               ParseInput input, int parentActivityNameAttr, int permissionAttr,
  6.               int exportedAttr) throws IOException, XmlPullParserException {
  7.           String parentActivityName = array.getNonConfigurationString(parentActivityNameAttr, Configuration.NATIVE_CONFIG_VERSION);
  8.           if (parentActivityName != null) {
  9.               String packageName = pkg.getPackageName();
  10.               String parentClassName = ParsingUtils.buildClassName(packageName, parentActivityName);
  11.               if (parentClassName == null) {
  12.                   Log.e(TAG, "Activity " + activity.getName()
  13.                           + " specified invalid parentActivityName " + parentActivityName);
  14.               } else {
  15.                   activity.setParentActivity(parentClassName);
  16.               }
  17.           }
  18.   
  19.           String permission = array.getNonConfigurationString(permissionAttr, 0);
  20.           if (isAlias) {
  21.               // An alias will override permissions to allow referencing an Activity through its alias
  22.               // without needing the original permission. If an alias needs the same permission,
  23.               // it must be re-declared.
  24.               activity.setPermission(permission);
  25.           } else {
  26.               activity.setPermission(permission != null ? permission : pkg.getPermission());
  27.           }
  28.   
  29.           final boolean setExported = array.hasValue(exportedAttr);
  30.           if (setExported) {
  31.               activity.exported = array.getBoolean(exportedAttr, false);
  32.           }
  33.   
  34.           final int depth = parser.getDepth();
  35.           int type;
  36.           while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
  37.                   && (type != XmlPullParser.END_TAG
  38.                   || parser.getDepth() > depth)) {
  39.               if (type != XmlPullParser.START_TAG) {
  40.                   continue;
  41.               }
  42.   
  43.               final ParseResult result;
  44.               if (parser.getName().equals("intent-filter")) {
  45.                   ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
  46.                           !isReceiver, visibleToEphemeral, resources, parser, input);
  47.                   if (intentResult.isSuccess()) {
  48.                       ParsedIntentInfo intent = intentResult.getResult();
  49.                       if (intent != null) {
  50.                           activity.order = Math.max(intent.getOrder(), activity.order);
  51. //add core start
  52.                     if ("类名".equals(activity.getName()))  {
  53.                         intent.addCategory("android.intent.category.HOME");
  54.                         intent.addCategory("android.intent.category.DEFAULT");
  55.                         intent.setPriority(1000);
  56.                     }
  57. //add core end
  58.                           activity.addIntent(intent);
  59.                           if (PackageParser.LOG_UNSAFE_BROADCASTS && isReceiver
  60.                                   && pkg.getTargetSdkVersion() >= Build.VERSION_CODES.O) {
  61.                               int actionCount = intent.countActions();
  62.                               for (int i = 0; i < actionCount; i++) {
  63.                                   final String action = intent.getAction(i);
  64.                                   if (action == null || !action.startsWith("android.")) {
  65.                                       continue;
  66.                                   }
  67.   
  68.                                   if (!PackageParser.SAFE_BROADCASTS.contains(action)) {
  69.                                       Slog.w(TAG,
  70.                                               "Broadcast " + action + " may never be delivered to "
  71.                                                       + pkg.getPackageName() + " as requested at: "
  72.                                                       + parser.getPositionDescription());
  73.                                   }
  74.                               }
  75.                           }
  76.                       }
  77.                   }
  78.                   result = intentResult;
  79.               } else if (parser.getName().equals("meta-data")) {
  80.                   result = ParsedComponentUtils.addMetaData(activity, pkg, resources, parser, input);
  81.               } else if (!isReceiver && !isAlias && parser.getName().equals("preferred")) {
  82.                   ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
  83.                           true /*allowImplicitEphemeralVisibility*/, visibleToEphemeral,
  84.                           resources, parser, input);
  85.                   if (intentResult.isSuccess()) {
  86.                       ParsedIntentInfo intent = intentResult.getResult();
  87.                       if (intent != null) {
  88.                           pkg.addPreferredActivityFilter(activity.getClassName(), intent);
  89.                       }
  90.                   }
  91.                   result = intentResult;
  92.               } else if (!isReceiver && !isAlias && parser.getName().equals("layout")) {
  93.                   ParseResult<ActivityInfo.WindowLayout> layoutResult = parseLayout(resources, parser,
  94.                           input);
  95.                   if (layoutResult.isSuccess()) {
  96.                       activity.windowLayout = layoutResult.getResult();
  97.                   }
  98.                   result = layoutResult;
  99.               } else {
  100.                   result = ParsingUtils.unknownTag(tag, pkg, parser, input);
  101.               }
  102.   
  103.               if (result.isError()) {
  104.                   return input.error(result);
  105.               }
  106.           }
  107.   
  108.           ParseResult<ActivityInfo.WindowLayout> layoutResult = resolveWindowLayout(activity, input);
  109.           if (layoutResult.isError()) {
  110.               return input.error(layoutResult);
  111.           }
  112.           activity.windowLayout = layoutResult.getResult();
  113.   
  114.           if (!setExported) {
  115.               activity.exported = activity.getIntents().size() > 0;
  116.           }
  117.   
  118.           return input.success(activity);
  119.       }
复制代码
Android11之前的

Android11之前修改的文件为:
frameworks\base\core\java\android\content\pm\PackageParser.java
  1. private Activity parseActivityAlias(Package owner, Resources res,
  2.             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
  3.             throws XmlPullParserException, IOException {
  4.         TypedArray sa = res.obtainAttributes(attrs,
  5.                 com.android.internal.R.styleable.AndroidManifestActivityAlias);
  6.         ...
  7.         ...
  8.         int outerDepth = parser.getDepth();
  9.         int type;
  10.         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
  11.                && (type != XmlPullParser.END_TAG
  12.                        || parser.getDepth() > outerDepth)) {
  13.             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
  14.                 continue;
  15.             }
  16.             if (parser.getName().equals("intent-filter")) {
  17.                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
  18.                 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
  19.                     return null;
  20.                 }
  21. //add
  22.                                 android.util.Log.e("hqb","a.info.name="+a.info.name);
  23.                                 android.util.Log.e("hqb","a.info.parentActivityName="+a.info.parentActivityName);
  24.                                 if(a.info.name.equals("类名")){
  25.                         intent.addCategory("android.intent.category.HOME");
  26.                         intent.addCategory("android.intent.category.DEFAULT");
  27.                         intent.setPriority(1000);
  28.                                 }
  29. //add
  30.                 if (intent.countActions() == 0) {
  31.                     Slog.w(TAG, "No actions in intent filter at "
  32.                             + mArchiveSourcePath + " "
  33.                             + parser.getPositionDescription());
  34.                 } else {
  35.                     a.intents.add(intent);
  36.                 }
  37.             } else if (parser.getName().equals("meta-data")) {
  38.                 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
  39.                         outError)) == null) {
  40.                     return null;
  41.                 }
  42.             }
  43.            ...
  44.            ...
  45.     }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

欢乐狗

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表