Android 源码多个Launcher设置默认Launcher

目录

第一部分、android10之前

[一.多个launcher 启动设置默认launcher的核心类](#一.多个launcher 启动设置默认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的相关源码

 @UiThread
  public class ResolverActivity extends Activity {  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          // Use a specialized prompt when we're handling the 'Home' app startActivity()
          final Intent intent = makeMyIntent();
          final Set<String> categories = intent.getCategories();
          if (Intent.ACTION_MAIN.equals(intent.getAction())
                  && categories != null
                  && categories.size() == 1
                  && categories.contains(Intent.CATEGORY_HOME)) {
              // Note: this field is not set to true in the compatibility version.
              mResolvingHome = true;
          }
  
          setSafeForwardingMode(true);
  
          onCreate(savedInstanceState, intent, null, 0, null, null, true);
      }
  
      /**
       * Compatibility version for other bundled services that use this overload without
       * a default title resource
       */
      @UnsupportedAppUsage
      protected void onCreate(Bundle savedInstanceState, Intent intent,
              CharSequence title, Intent[] initialIntents,
              List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
          onCreate(savedInstanceState, intent, title, 0, initialIntents, rList,
                  supportsAlwaysUseOption);
      }
  
      protected void onCreate(Bundle savedInstanceState, Intent intent,
              CharSequence title, int defaultTitleRes, Intent[] initialIntents,
              List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
          setTheme(R.style.Theme_DeviceDefault_Resolver);
          super.onCreate(savedInstanceState);
  
          // Determine whether we should show that intent is forwarded
          // from managed profile to owner or other way around.
          setProfileSwitchMessageId(intent.getContentUserHint());
  
          try {
              mLaunchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid(
                      getActivityToken());
          } catch (RemoteException e) {
              mLaunchedFromUid = -1;
          }
  
          if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
              // Gulp!
              finish();
              return;
          }
  
          mPm = getPackageManager();
  
          mPackageMonitor.register(this, getMainLooper(), false);
          mRegistered = true;
          mReferrerPackage = getReferrerPackageName();
  
          final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
          mIconDpi = am.getLauncherLargeIconDensity();
  
          // Add our initial intent as the first item, regardless of what else has already been added.
          mIntents.add(0, new Intent(intent));
          mTitle = title;
          mDefaultTitleResId = defaultTitleRes;
  
          mUseLayoutForBrowsables = getTargetIntent() == null
                  ? false
                  : isHttpSchemeAndViewAction(getTargetIntent());
  
          mSupportsAlwaysUseOption = supportsAlwaysUseOption;
  
          if (configureContentView(mIntents, initialIntents, rList)) {
              return;
          }
  
          final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
          if (rdl != null) {
              rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
                  @Override
                  public void onDismissed() {
                      finish();
                  }
              });
              if (isVoiceInteraction()) {
                  rdl.setCollapsed(false);
              }
  
              rdl.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                      | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
              rdl.setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
  
              mResolverDrawerLayout = rdl;
          }
  
          mProfileView = findViewById(R.id.profile_button);
          if (mProfileView != null) {
              mProfileView.setOnClickListener(this::onProfileClick);
              bindProfileView();
          }
  
          initSuspendedColorMatrix();
  
          if (isVoiceInteraction()) {
              onSetupVoiceInteraction();
          }
          final Set<String> categories = intent.getCategories();
          MetricsLogger.action(this, mAdapter.hasFilteredItem()
                  ? MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_APP_FEATURED
                  : MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_NONE_FEATURED,
                  intent.getAction() + ":" + intent.getType() + ":"
                          + (categories != null ? Arrays.toString(categories.toArray()) : ""));
      } 

在ResolverActivity.java中的onCreate中首先读取系统中的Home属性的Launcher列表,然后在

ResolveListAdapter中展示Launcher的列表,所以可以在这些直接设置默认的Launcher,然后finish掉这个页面,直接进入默认Launcher页面

具体修改为:

--- a/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
+++ b/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
@@ -278,9 +278,53 @@ public class ResolverActivity extends Activity {
         intent.setFlags(intent.getFlags()&~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         return intent;
     }
-
+    private void setDefaultLauncher(String defPackageName,String defClassName) {
+        if ((defPackageName != null && defPackageName.trim().length() > 1) && (defClassName != null && defClassName.trim().length() > 0)) {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction("android.intent.action.MAIN");
+            filter.addCategory("android.intent.category.HOME");
+            filter.addCategory("android.intent.category.DEFAULT");
+
+            Intent intent=new Intent(Intent.ACTION_MAIN);
+            intent.addCategory(Intent.CATEGORY_HOME);
+            List<ResolveInfo> list = new ArrayList<ResolveInfo>();
+            list = getPackageManager().queryIntentActivities(intent, 0);
+            final int N = list.size();
+            ComponentName[] set = new ComponentName[N];
+            int bestMatch = 0;
+            for (int i=0; i<N; i++) {
+                ResolveInfo r = list.get(i);
+                set[i] = new ComponentName(r.activityInfo.packageName,
+                        r.activityInfo.name);
+               if (r.match > bestMatch) bestMatch = r.match;
+            }
+            ComponentName preActivity = new ComponentName(defPackageName, defClassName);
+            getPackageManager().addPreferredActivity(filter, bestMatch, set,preActivity);
+        }
+    }
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+                   boolean firstBoot = (Settings.Global.getInt(getApplication().getContentResolver(),
+                    "default_home_launcher", 0) == 0);
+                       String defPackageName = Settings.Global.getString(getContentResolver(),"launcher_pkgname");
+                       String defClassName = Settings.Global.getString(getContentResolver(),"launcher_classname");
+                       Log.e(TAG,"pkgname:"+defPackageName+"---defClassName:"+defClassName);
+        if(firstBoot &&!TextUtils.isEmpty(defPackageName)){
+                       try {
+              setDefaultLauncher(defPackageName,defClassName);
+                     Intent defIntent = new Intent();
+              defIntent.setClassName(defPackageName, defClassName);
+              defIntent.setAction("android.intent.action.MAIN");
+              defIntent.addCategory("android.intent.category.HOME");
+              defIntent.addCategory("android.intent.category.DEFAULT");
+              startActivity(defIntent);
+              Settings.Global.putInt(getApplication().getContentResolver(),
+                    "default_home_launcher",1);
+              this.finish();
+                       } catch (Exception e) {
+              e.printStackTrace();
+                       }
+        }
         ActivityDebugConfigs.addConfigChangedListener(mDebugConfigListener);
 
         // Use a specialized prompt when we're handling the 'Home' app startActivity()
@@ -1291,7 +1335,6 @@ public class ResolverActivity extends Activity {
         setContentView(mLayoutId);

在onCreate中的增加setDefaultLauncher(String defPackageName,String defClassName)这个设置默认Launcher的方法,而PM的addPreferredActivity设置默认Launcher,就实现了功能

二 在自定义服务里面设置默认Launcher

public class MdmManagerService extends IMdmManager.Stub {
	private static String TAG ="MdmManagerService";
    private Context mContext;
    private Handler mHandler = new Handler(Looper.getMainLooper());
    public MdmManagerService(Context context){
        this.mContext = context;
		mHandler.postDelayed(mRunnable, 0);
        //IntentFilter mintent=new IntentFilter("com.sprd.settings.action.apistart");
        //mContext.registerReceiver(mBroadcastReceiver,mintent);
    }
    private BroadcastReceiver mBroadcastReceiver =new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e(TAG,"action");
			//mHandler.postDelayed(mRunnable, 500);
        }
    };
    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "actionRun");
            try {
                //setStatusBarExpandPanelDisabled(true);
				String defaultLauncher = SystemProperties.get("persist.sys.ployer.default.launcher", "");
                if(TextUtils.isEmpty(defaultLauncher)){
                   setDefaultLauncher("com.android.launcher3", "com.android.launcher3.Launcher");
                   //setDefaultLauncher("com.ployer.interfacedemo", "com.ployer.interfacedemo.MainActivity");
		        }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private void setDefaultApplication(String roleName, String packageName) {
        RoleManager roleManager = mContext.getSystemService(RoleManager.class);
        Executor executor = mContext.getMainExecutor();
        Consumer<Boolean> callback = successful -> {
            if (successful) {
                Log.e(TAG, "setDefaultApplication packageName:"+packageName+" successful");
            }
        };
        roleManager.addRoleHolderAsUser(roleName, packageName, 0, android.os.Process.myUserHandle(), executor, callback);
    }
    public void setDefaultLauncher(String packageName, String className) throws RemoteException {
       Log.e(TAG, "setDefaultLauncher:packageName="+packageName+"--className:"+className);
       final long ident = Binder.clearCallingIdentity();
       try {
            if (isPkgInstalled(mContext, packageName)) {
			    Settings.Global.putString(mContext.getContentResolver(),"launcher_pkgname",packageName);
			    Settings.Global.putString(mContext.getContentResolver(),"launcher_classname",className);
                String value = packageName + "/" + className;
                SystemProperties.set("persist.sys.ployer.default.launcher", value);
				setDefaultApplication("android.app.role.HOME",packageName);
            } else {
                Log.e(TAG, "setDefaultLauncher packageName is not exist");
            }
	   } catch (Exception e) {
          e.printStackTrace();
       }finally {
          Binder.restoreCallingIdentity(ident);
       }
    }
    private boolean isPkgInstalled(Context context, String packageName) {
        if (packageName == null || "".equals(packageName))
            return false;
        ApplicationInfo info = null;
        try {
            info = context.getPackageManager().getApplicationInfo(packageName, 0);
            return info != null;
        } catch (Exception e) {
            Log.e(TAG, "apk is not installed packageName:" + packageName);
            return false;
        }
    }

第二部分、android10之后

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

主要利用ResolverActivity.java或ActivityManagerService.java来实现,接下来我将分别举例说明:

1.通过ResolverActivity.java设置为默认Launcher

主要是由addPreferredActivity设置默认Launcher实现。

改法一:

代码路径:frameworks/base/core/java/com/android/internal/app/ResolverActivity.java

以下基于Android11代码:

protected void onCreate(Bundle savedInstanceState, Intent intent,
            CharSequence title, int defaultTitleRes, Intent[] initialIntents,
            List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
        setTheme(appliedThemeResId());
        super.onCreate(savedInstanceState);
 
        //add
           if(mResolvingHome){
            setDefaultLauncher();
            finish();
            return;
        }
        //add
        ...
        }
 
 
private void setDefaultLauncher() {
            try {
                final PackageManager pm = getPackageManager();
                String defPackageName = "com.android.launcher3";//默认launcher包名
                String defClassName = "com.android.searchlauncher.SearchLauncher";//默认launcher类名
                IntentFilter filter = new IntentFilter();
                filter.addAction("android.intent.action.MAIN");
                filter.addCategory("android.intent.category.HOME");
                filter.addCategory("android.intent.category.DEFAULT");
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_HOME);
                List<ResolveInfo> list = new ArrayList<ResolveInfo>();
                list = pm.queryIntentActivities(intent, 0);
                final int N = list.size();
                ComponentName[] set = new ComponentName[N];
                int bestMatch = 0;
                for (int i = 0; i < N; i++) {
                    ResolveInfo r = list.get(i);
                    set[i] = new ComponentName(r.activityInfo.packageName,
                            r.activityInfo.name);
                    if (r.match > bestMatch) bestMatch = r.match;
                }
                ComponentName preActivity = new ComponentName(defPackageName, defClassName);
                pm.addPreferredActivity(filter, bestMatch, set, preActivity);
 
            } catch (Exception e) {
                e.printStackTrace();
            }
 
    }
改法二:

代码路径:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

boolean startHomeActivityLocked(int userId, String reason) {
		setDefaultLauncher();//调用设置默认launcher方法
		SystemProperties.set("persist.sys.boot.bootcomplete","1");
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // We are running in factory test mode, but unable to find
            // the factory test app, so just sit around displaying the
            // error message and don't try to start anything.
            return false;
        }
 
    ...
    ...
}
 
 
private void setDefaultLauncher() {
            boolean mFirstLaunch = true;
            String packageName = "包名";//launcher包名
            String className = "类名";
            if ((packageName != null && packageName.trim().length() > 1) && (className != null && className.trim().length() > 0)) {
                if(mFirstLaunch){
                    IPackageManager pm = ActivityThread.getPackageManager();
                    ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>();
                    ArrayList<ComponentName> cnList = new ArrayList<ComponentName>();
                    mContext.getPackageManager().getPreferredActivities(intentList, cnList, null);
                    IntentFilter dhIF;
                    for(int i = 0; i < cnList.size(); i++){
                        dhIF = intentList.get(i);
                        if(dhIF.hasAction(Intent.ACTION_MAIN) &&
                                dhIF.hasCategory(Intent.CATEGORY_HOME)) {
                            mContext.getPackageManager().clearPackagePreferredActivities(cnList.get(i).getPackageName());
                        }
                    }
                    Intent intent = new Intent(Intent.ACTION_MAIN);
                    intent.addCategory(Intent.CATEGORY_HOME);
                    List<ResolveInfo> list = new ArrayList<ResolveInfo>();
                    try {
                        list = pm.queryIntentActivities(intent,
                                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                PackageManager.MATCH_DEFAULT_ONLY,UserHandle.getCallingUserId()).getList(); //add .getList()
                    }catch (RemoteException e) {
                        throw new RuntimeException("Package manager has died", e);
                    }
                    IntentFilter filter = new IntentFilter();
                    filter.addAction(Intent.ACTION_MAIN);
                    filter.addCategory(Intent.CATEGORY_HOME);
                    filter.addCategory(Intent.CATEGORY_DEFAULT);
                    final int N = list.size();
                    ComponentName[] set = new ComponentName[N];
                    int bestMatch = 0;
                    for (int i = 0; i < N; i++)
                    {
                        ResolveInfo r = list.get(i);
                        set[i] = new ComponentName(r.activityInfo.packageName,
                                r.activityInfo.name);
                        if (r.match > bestMatch) bestMatch = r.match;
                    }
                    ComponentName launcher = new ComponentName(packageName, className);
                    try{
                        pm.addPreferredActivity(filter, bestMatch, set, launcher,UserHandle.getCallingUserId());
                    } catch (RemoteException e) {
                        throw new RuntimeException("Package manager has died", e);
                    }
                }
            }
        }

2.通过ActivityManagerService.java设置为默认Launcher

主要修改getHomeIntent(),将其替换成需要默认的Launcher即可。

代码路径:frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

改法一(常规):
Intent getHomeIntent() {
//add
		Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
			String defStartPkg = "你的包名";
			Intent queryIntent = new Intent();
			final PackageManager mPm = mContext.getPackageManager();
			queryIntent.addCategory(Intent.CATEGORY_HOME);///没有home可去掉
			queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
			queryIntent.setAction(Intent.ACTION_MAIN);
			List<ResolveInfo> homeActivities = mPm.queryIntentActivities(queryIntent, 0);
			if(homeActivities != null) {
				int activityNum = homeActivities.size();
				ComponentName[] set = new ComponentName[activityNum];
				for(int i = 0; i < activityNum; i++){
					ResolveInfo info = homeActivities.get(i);
					set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
					if(defStartPkg.equals(info.activityInfo.packageName)){
						Intent intentaa = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
						intentaa.setComponent(set[i]);
						intentaa.addCategory(Intent.CATEGORY_HOME);
						return intentaa;
					}
				}
			}
//add
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }
改法二(简化):
Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        //add
        //intent.setComponent(mTopComponent);
        intent.setComponent(new ComponentName("包名", "类名"));
        //add
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

二、普通应用内置并设置为默认Launcher

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

1.强制替换

首先将应用设置为默认开机启动,但因为没有android.intent.category.HOME这个Category所以提供通过ResolverActivity.java设置是不行的,需要通过修改ActivityManagerService.java来实现,只要把改法一中的queryIntent.addCategory(Intent.CATEGORY_HOME);注释掉即可:

Intent getHomeIntent() {
//add
		Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
			String defStartPkg = "你的包名";
			Intent queryIntent = new Intent();
			final PackageManager mPm = mContext.getPackageManager();
			//queryIntent.addCategory(Intent.CATEGORY_HOME);///没有home可去掉
			queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
			queryIntent.setAction(Intent.ACTION_MAIN);
			List<ResolveInfo> homeActivities = mPm.queryIntentActivities(queryIntent, 0);
			if(homeActivities != null) {
				int activityNum = homeActivities.size();
				ComponentName[] set = new ComponentName[activityNum];
				for(int i = 0; i < activityNum; i++){
					ResolveInfo info = homeActivities.get(i);
					set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
					if(defStartPkg.equals(info.activityInfo.packageName)){
						Intent intentaa = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
						intentaa.setComponent(set[i]);
						intentaa.addCategory(Intent.CATEGORY_HOME);
						return intentaa;
					}
				}
			}
//add
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

通过上面的修改就可以开机默认启动了,但是会出现按home、recent、back键会退出应用从而进入原生Launcher的情况,所以我们需要对这些按键进行拦截定制:

代码路径:frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

 mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
//add
		ComponentName mHomecom = new ComponentName("包名", "类名"); 
        mHomeIntent.setComponent(mHomecom);
//add
        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 
 
@Override
    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
....
....
//add
if(keyCode == KeyEvent.KEYCODE_BACK){	if(getClsName(mContext).equals("com.ryanheise.audioservice.AudioServiceFragmentActivity")
			&&(getInputMethodWindowVisibleHeightLw()==0)){
			return -1;
			}
		}
//add
....
....
}
 
private String getClsName(Context context) {
        try {
             ActivityManager am = context.getSystemService(ActivityManager.class);
             List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
             return tasks.get(0).topActivity.getClassName();
        } catch (Exception e) {
           //ignore
        }
        return "";
    }

代码路径:SystemUI\src\com\android\systemui\recents\RecentsActivity.java

import android.content.ComponentName;
 
 Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
         homeIntent.addCategory(Intent.CATEGORY_HOME);
         ComponentName mHomecom = new ComponentName("包名", "类名"); 
         homeIntent.setComponent(mHomecom);
         homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                 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

      @NonNull
      private static ParseResult<ParsedActivity> parseActivityOrAlias(ParsedActivity activity,
              ParsingPackage pkg, String tag, XmlResourceParser parser, Resources resources,
              TypedArray array, boolean isReceiver, boolean isAlias, boolean visibleToEphemeral,
              ParseInput input, int parentActivityNameAttr, int permissionAttr,
              int exportedAttr) throws IOException, XmlPullParserException {
          String parentActivityName = array.getNonConfigurationString(parentActivityNameAttr, Configuration.NATIVE_CONFIG_VERSION);
          if (parentActivityName != null) {
              String packageName = pkg.getPackageName();
              String parentClassName = ParsingUtils.buildClassName(packageName, parentActivityName);
              if (parentClassName == null) {
                  Log.e(TAG, "Activity " + activity.getName()
                          + " specified invalid parentActivityName " + parentActivityName);
              } else {
                  activity.setParentActivity(parentClassName);
              }
          }
  
          String permission = array.getNonConfigurationString(permissionAttr, 0);
          if (isAlias) {
              // An alias will override permissions to allow referencing an Activity through its alias
              // without needing the original permission. If an alias needs the same permission,
              // it must be re-declared.
              activity.setPermission(permission);
          } else {
              activity.setPermission(permission != null ? permission : pkg.getPermission());
          }
  
          final boolean setExported = array.hasValue(exportedAttr);
          if (setExported) {
              activity.exported = array.getBoolean(exportedAttr, false);
          }
  
          final int depth = parser.getDepth();
          int type;
          while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                  && (type != XmlPullParser.END_TAG
                  || parser.getDepth() > depth)) {
              if (type != XmlPullParser.START_TAG) {
                  continue;
              }
  
              final ParseResult result;
              if (parser.getName().equals("intent-filter")) {
                  ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
                          !isReceiver, visibleToEphemeral, resources, parser, input);
                  if (intentResult.isSuccess()) {
                      ParsedIntentInfo intent = intentResult.getResult();
                      if (intent != null) {
                          activity.order = Math.max(intent.getOrder(), activity.order);
 
//add core start
                    if ("类名".equals(activity.getName()))  {
                        intent.addCategory("android.intent.category.HOME");
                        intent.addCategory("android.intent.category.DEFAULT");
                        intent.setPriority(1000);
                    }
//add core end
 
                          activity.addIntent(intent);
                          if (PackageParser.LOG_UNSAFE_BROADCASTS && isReceiver
                                  && pkg.getTargetSdkVersion() >= Build.VERSION_CODES.O) {
                              int actionCount = intent.countActions();
                              for (int i = 0; i < actionCount; i++) {
                                  final String action = intent.getAction(i);
                                  if (action == null || !action.startsWith("android.")) {
                                      continue;
                                  }
  
                                  if (!PackageParser.SAFE_BROADCASTS.contains(action)) {
                                      Slog.w(TAG,
                                              "Broadcast " + action + " may never be delivered to "
                                                      + pkg.getPackageName() + " as requested at: "
                                                      + parser.getPositionDescription());
                                  }
                              }
                          }
                      }
                  }
                  result = intentResult;
              } else if (parser.getName().equals("meta-data")) {
                  result = ParsedComponentUtils.addMetaData(activity, pkg, resources, parser, input);
              } else if (!isReceiver && !isAlias && parser.getName().equals("preferred")) {
                  ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
                          true /*allowImplicitEphemeralVisibility*/, visibleToEphemeral,
                          resources, parser, input);
                  if (intentResult.isSuccess()) {
                      ParsedIntentInfo intent = intentResult.getResult();
                      if (intent != null) {
                          pkg.addPreferredActivityFilter(activity.getClassName(), intent);
                      }
                  }
                  result = intentResult;
              } else if (!isReceiver && !isAlias && parser.getName().equals("layout")) {
                  ParseResult<ActivityInfo.WindowLayout> layoutResult = parseLayout(resources, parser,
                          input);
                  if (layoutResult.isSuccess()) {
                      activity.windowLayout = layoutResult.getResult();
                  }
                  result = layoutResult;
              } else {
                  result = ParsingUtils.unknownTag(tag, pkg, parser, input);
              }
  
              if (result.isError()) {
                  return input.error(result);
              }
          }
  
          ParseResult<ActivityInfo.WindowLayout> layoutResult = resolveWindowLayout(activity, input);
          if (layoutResult.isError()) {
              return input.error(layoutResult);
          }
          activity.windowLayout = layoutResult.getResult();
  
          if (!setExported) {
              activity.exported = activity.getIntents().size() > 0;
          }
  
          return input.success(activity);
      } 

Android11之前的

Android11之前修改的文件为:

frameworks\base\core\java\android\content\pm\PackageParser.java

private Activity parseActivityAlias(Package owner, Resources res,
            XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
            throws XmlPullParserException, IOException {
        TypedArray sa = res.obtainAttributes(attrs,
                com.android.internal.R.styleable.AndroidManifestActivityAlias);
 
        ...
        ...
        int outerDepth = parser.getDepth();
        int type;
        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
               && (type != XmlPullParser.END_TAG
                       || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }
 
            if (parser.getName().equals("intent-filter")) {
                ActivityIntentInfo intent = new ActivityIntentInfo(a);
                if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
                    return null;
                }
//add
				android.util.Log.e("hqb","a.info.name="+a.info.name);
				android.util.Log.e("hqb","a.info.parentActivityName="+a.info.parentActivityName);
				if(a.info.name.equals("类名")){
                        intent.addCategory("android.intent.category.HOME");
                        intent.addCategory("android.intent.category.DEFAULT");
                        intent.setPriority(1000);
				}
//add
                if (intent.countActions() == 0) {
                    Slog.w(TAG, "No actions in intent filter at "
                            + mArchiveSourcePath + " "
                            + parser.getPositionDescription());
                } else {
                    a.intents.add(intent);
                }
            } else if (parser.getName().equals("meta-data")) {
                if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
                        outError)) == null) {
                    return null;
                }
            } 
           ...
           ... 
    }
相关推荐
帅得不敢出门6 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了8 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任9 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山9 小时前
Android“引用们”的底层原理
android·java
迃-幵10 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶10 小时前
Android——从相机/相册获取图片
android
Rverdoser10 小时前
Android Studio 多工程公用module引用
android·ide·android studio
aaajj11 小时前
[Android]从FLAG_SECURE禁止截屏看surface
android
@OuYang11 小时前
android10 蓝牙(二)配对源码解析
android
Liknana11 小时前
Android 网易游戏面经
android·面试