Android 源码多个Launcher设置默认Launcher

目录

第一部分、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的相关源码

 @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;
                }
            } 
           ...
           ... 
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/879168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

buildroot移植qt报错Info: creating stash file (补充qt添加字库)

移植qt库&#xff0c;编译文件报错Info: creating stash file /home/rbing/QT/uart/.qmake.stash Project ERROR: Unknown module(s) in QT: serialport rbingouc:~/QT/uart$ /home/rbing/linux/tool/buildroot-2022.02.9/output/host/usr/bin/qmake Info: creating stash fil…

【LeetCode】每日一题 2024_9_18 坐上公交的最晚时间(排序,模拟)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;坐上公交的最晚时间 代码与解题思路 func latestTimeCatchTheBus(buses []int, passengers []int, capacity int) (ans int) {// 核心思路分析&#xff1a;// 你可以搭乘公交车的最晚到达…

【数据仓库】数据仓库常见的数据模型——维度模型

文章部分图参考自&#xff1a;多维数据模型各种类型&#xff08;星型、雪花、星座、交叉连接&#xff09; - 知乎 (zhihu.com) 文章部分文字canla一篇文章搞懂数据仓库&#xff1a;四种常见数据模型&#xff08;维度模型、范式模型等&#xff09;-腾讯云开发者社区-腾讯云 (ten…

React18快速入门

需要先安装并配置React相关的工具和插件 下载安装Node.js&#xff0c;这里以MacOS Node.js v22.6.0为例 终端命令行检查是否安装成功 node -v npm -vNode.js快速入门 npm设置镜像源 #设置为阿里镜像源 npm config set registry https://registry.npmmirror.com #查看是否生…

初始Linux 和 各种常见指令

目录 Linux背景 1. 发展史 Linux发展历史 1.历史 2. 开源 Linux下基本指令 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令&#xff08;重要&#xff09;&#xff1a; 06.rmdir指令 && rm 指令&#xff08;重要&#xff09;&#xff1a; …

Minio环境搭建(单机安装包、docker)(一)

前言&#xff1a; 项目中客户不愿意掏钱买oss&#xff0c;无奈只能给他免费大保健来一套。本篇文章只是记录验证可行性&#xff0c;毕竟minio太少文档了&#xff0c;参考着官网来。后面还会再出一套验证集群部署的文章。 一、资料 MinIO官网&#xff1a; MinIO | S3 Compatib…

web渗透—RCE

一&#xff1a;代码执行 相关函数 1、eval()函数 assert()函数 (1)原理&#xff1a;将用户提交或者传递的字符串当作php代码执行 (2)passby:单引号绕过&#xff1a;闭合注释&#xff1b;开启GPC的话就无法绕过&#xff08;GPC就是将单引号转换为"反斜杠单引号"&a…

基于python+django+vue的鲜花商城系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的线…

[数据集][目标检测]俯拍航拍森林火灾检测数据集VOC+YOLO格式6116张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6116 标注数量(xml文件个数)&#xff1a;6116 标注数量(txt文件个数)&#xff1a;6116 标注…

图像滤波---各项异性扩散滤波使用笔记及代码

图像滤波---各项异性扩散滤波使用笔记及代码 一、文章内容介绍二、各项异性扩散滤波和各项同性滤波1、各项同性滤波2、各项异性扩散滤波3、各项异性和各项同性的对比 三、各项异性扩散滤波的原理介绍四、各项异性扩散滤波公式五、公式中的参数使用说明1、扩散速率 λ \lambda λ…

【C++】虚函数

一、什么是虚函数 在类的成员函数前加上virtual关键字&#xff0c;这个函数就是虚函数。 虚函数的所用就是完成多态。多态示例如下&#xff1a; class A {public:virtual void func()//虚函数{cout << "A" << endl;}void ftwo()//普通函数{cout <&…

黑神话·悟空藕丝步云履怎么获得?来看这一篇

1、传送到花果山-山脚-青嶂道土地庙。 2、在这里召唤筋斗云飞行岛章节刚开始的的初始位置方向 在这里推荐一款旗舰开放式耳机南卡OE Pro2&#xff0c;在目前有许多开放式耳机产品存在佩戴舒适度低且音质表现非常一般的当下&#xff0c;南卡开放式耳机凭借“非常规”的软硬结合…

Vue2电商平台项目 (三) Search模块、面包屑(页面自己跳自己)、排序、分页器!

文章目录 一、Search模块1、Search模块的api2、Vuex保存数据3、组件获取vuex数据并渲染(1)、分析请求数据的数据结构(2)、getters简化数据、渲染页面 4、Search模块根据不同的参数获取数据(1)、 派发actions的操作封装为函数(2)、设置带给服务器的参数(3)、Object.assign整理参…

智慧宿舍平台|基于Springboot+vue的智慧宿舍系统(源码+数据库+文档)

智慧宿舍系统 目录 基于Springbootvue的智慧宿舍系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xff0c;阿里云开发社区乘风者…

java多线程模拟多个售票员从同一个票池售票

程序功能 这段代码模拟了多个售票员从一个有限的票池中售票的过程。主要功能如下&#xff1a; 票池共有50张票&#xff0c;多个售票员&#xff08;线程&#xff09;并发进行售票。 使用同步机制确保线程安全&#xff0c;避免多个售票员同时出售同一张票。 每个售票员不断检查票…

51单片机 - DS18B20实验1-读取温度

上来一张图&#xff0c;明确思路&#xff0c;程序整体裤架如下&#xff0c;通过单总线&#xff0c;单独封装一个.c文件用于单总线的操作&#xff0c;其实&#xff0c;我们可以把点c文件看成一个类操作&#xff0c;其属性就是我们面向对象的函数&#xff0c;也叫方法&#xff0c…

软考中级软件设计师——数据结构与算法基础学习笔记

软考中级软件设计师——数据结构与算法基本概念 什么是数据数据元素、数据项数据结构逻辑结构物理结构&#xff08;存储结构&#xff09; 算法什么是算法五个特性算法效率的度量时间复杂度空间复杂度 什么是数据 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所…

【算法】队列与BFS

【ps】本篇有 4 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;N 叉树的层序遍历 .1- 题目解析 .2- 代码编写 2&#xff09;二叉树的锯齿形层序遍历 .1- 题目解析 .2- 代码编写 3&#xff09;二叉树最大宽度 .1- 题目解析 .2- 代码编写 4&#xf…

自养号测评:如何在敦煌网打造爆款与提升店铺权重

敦煌网自养号测评是敦煌网卖家为了提升店铺权重、流量及销量而采取的一种策略。自养号测评指的是卖家自行注册并管理买家账号&#xff0c;通过模拟真实买家行为&#xff0c;为自家店铺进行测评、补单等操作。以下是对敦煌网自养号测评的详细解析&#xff1a; 一、自养号测评的…

Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法

Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法 Text-to-SQL 任务旨在将自然语言查询转换为结构化查询语言(SQL),从而使非专业用户能够便捷地访问和操作数据库。近期,阿里云的 OpenSearch 引擎凭借其一致性对齐技术,在当前极具影响力的 Text-to-SQL 任务…