Android 源码多个Launcher设置默认Launcher

news/2024/9/19 8:37:21/ 标签: android

目录

android10%E4%B9%8B%E5%89%8D-toc" style="margin-left:0px;">第一部分、android10之前

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

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

android10%E4%B9%8B%E5%90%8E-toc" style="margin-left:0px;">第二部分、android10之后

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

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

  改法一:

改法二:

2.通过ActivityManagerService.java设置为默认Launcher主要修改getHomeIntent(),将其替换成需要默认的Launcher即可。

改法一(常规):

改法二(简化):

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

1.强制替换

2.添加属性

Android11之前的


在Android系统中,设置默认Launcher(启动器)是一个涉及系统权限和配置的过程。通常,这个过程不是通过简单地修改几个文件或设置就能完成的,因为它需要系统级别的权限。不过,我可以概述一下在Android源码级别如何设置或允许用户选择默认Launcher的大致步骤。

android10%E4%B9%8B%E5%89%8D">第一部分、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的相关源码

 @UiThreadpublic class ResolverActivity extends Activity {  @Overrideprotected 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*/@UnsupportedAppUsageprotected 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() {@Overridepublic 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);
+        }
+    }@Overrideprotected 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() {@Overridepublic void onReceive(Context context, Intent intent) {Log.e(TAG,"action");//mHandler.postDelayed(mRunnable, 500);}};private Runnable mRunnable = new Runnable() {@Overridepublic 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%E4%B9%8B%E5%90%8E">第二部分、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);//addif(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() {
//addSettings.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;}}}
//addIntent 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("包名", "类名"));//addintent.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() {
//addSettings.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;}}}
//addIntent 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);
//addComponentName mHomecom = new ComponentName("包名", "类名"); mHomeIntent.setComponent(mHomecom);
//addmHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); @Overridepublic 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

 @NonNullprivate 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 startif ("类名".equals(activity.getName()))  {intent.addCategory("android.intent.category.HOME");intent.addCategory("android.intent.category.DEFAULT");intent.setPriority(1000);}
//add core endactivity.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;}
//addandroid.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);}
//addif (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.ppmy.cn/news/1526492.html

相关文章

Python——俄罗斯方块

俄罗斯方块游戏是一款经典的益智游戏&#xff0c;通常使用编程语言Python来实现。下面是一个简单的俄罗斯方块游戏的示例代码&#xff1a; import pygame import random# 定义颜色 BLACK (0, 0, 0) WHITE (255, 255, 255) RED (255, 0, 0) GREEN (0, 255, 0) BLUE (0, 0,…

Linux:进程(一)

目录 一、概念的理解 二、指令&#xff08;1&#xff09; 一、概念的理解 在许多地方对进程的定义都是这样的一句话&#xff1a;加载到内存中的程序、正在运行的程序、进程可以排队 而要真正理解进程是什么&#xff0c;这一句话的解释远远不够。 在定义进程之前&#xff0c;先…

CSS传统布局方法(补充)——WEB开发系列37

开发技术不断演进&#xff0c;布局方式也经历了多个阶段的变革。从最初的基于表格布局到 CSS 的浮动布局&#xff0c;再到今天的弹性盒&#xff08;Flexbox&#xff09;与 CSS Grid 网格布局&#xff0c;每一种布局方式都有其独特的背景和解决特定问题的优势。 一、CSS Grid 出…

2024 RSTCONCTF re 部分wp

Unknown Architect DIE查看&#xff0c;RISC_V架构&#xff0c;直接交即可 Duke of the Kingdom 附件拖入jadx 比较简单。脚本 Keypad 附件拖入ida。一共四遍check&#xff0c;都比较简单 Pico-Cypher 文本编辑器打开附件 稍微问一问gpt&#xff0c;得知这是micropython&#x…

春意盎然:SpringBoot在线教育平台设计

第五章 系统实现 5.1用户功能模块 用户点击进入到系统操作界面&#xff0c;可以对首页、个人中心、课程信息管理、我的收藏管理、订单管理等功能模块&#xff0c;个人信息&#xff1a;通过列表可以获取账号、密码、姓名、性别、手机、邮箱、照片、备注并进行修改操作&#xff…

FPGA 学习仿真硬件设计

- 封装常用的testbench&#xff0c;使用task或function进行代码封装&#xff0c;以便下次灵活调用。 - 当待测试文件中存在双向信号(inout)时&#xff0c;需要使用reg变量表示输入和wire变量表示输出。 - 尽量避免单个initial语句过于复杂&#xff0c;可以分开写成多个initia…

秒验HarmonyOS NEXT集成指南

开发工具&#xff1a;DevEco Studio 集成方式&#xff1a;在线集成 HarmonyOS API支持&#xff1a;> 12 集成前准备 注册账号 使用MobSDK之前&#xff0c;需要先在MobTech官网注册开发者账号&#xff0c;并获取MobTech提供的AppKey和AppSecret&#xff0c;详情可以点击查看…

基于小程序的教学辅助微信小程序设计+ssm(lw+演示+源码+运行)

教学辅助微信小程序 摘 要 随着移动应用技术的发展&#xff0c;越来越多的学生借助于移动手机、电脑完成生活中的事务&#xff0c;许多的传统行业也更加重视与互联网的结合&#xff0c;由于学生学习的压力越来越大&#xff0c;教学辅助是一个非常不错的教育平台&#xff0c;对…

HOT 100(七)栈、堆、贪心算法

一、栈 1、每日温度 使用单调递减栈来解决。主要思路是遍历temperatures数组&#xff0c;利用栈来存储还没有找到比当前温度高的天数的索引。当遇到比栈顶索引所对应温度更高的温度时&#xff0c;就可以确定当前这一天的温度比之前那一天高。索引的差值就是等待的天数。 求一…

DFS算法专题(四)——综合练习【含矩阵回溯】【含3道力扣困难级别算法题】

目录 1、字母大小写全排列 1.1 算法原理 1.2 算法代码 2、优美的排列 2.1 算法原理 2.2 算法代码 3、N皇后【困难】★★★ 3.1 算法原理 3.2 算法代码 4、有效的数独【解数独铺垫】 4.1 算法原理 4.2 算法代码 5、解数独【困难】★★★ 5.1 算法原理 5.2 算法代码…

vue原理分析(十四)研究new Vue()中的 initProvide

在Vue.prototype._init 中有一些init函数&#xff0c;今天我们来研究这些init函数 Vue.prototype._init function (options) {......{initProxy(vm);}......initLifecycle(vm);initEvents(vm);initRender(vm);callHook$1(vm, beforeCreate, undefined, false /* setContext *…

【软件测试面试题】WEB功能测试(持续更新)

Hi&#xff0c;大家好。最近很多朋友都在说今年的互联网行情不好&#xff0c;面试很难&#xff0c;不知道怎么复习&#xff0c;我最近总结了一份在软件测试面试中比较常见的WEB功能测试面试面试题合集&#xff0c;希望对大家有帮助。 建议点赞收藏再阅读&#xff0c;防止丢失&…

uView使用心得

说实话我不爱用这个库&#xff0c;感觉很鸡肋&#xff0c;坑很多&#xff0c;可能没用习惯 picker选择器 绑定默认值是通过设置index&#xff0c;并且这个index需要通过api设置进去&#xff0c;设置defalutindex绑定值无效&#xff08;只有初始化可以&#xff0c;后面动态改变…

uni-app 应用名称 跟随系统语言 改变

官方已确认BUG:&#xff1a;https://ask.dcloud.net.cn/question/164804 { "name" : "%app.name%",//这里随便写&#xff0c;配置了 locales,name 就不生效了 "appid" : "", "description" : "", "versi…

虚幻引擎 | (类恐鬼症)玩家和NPC语音聊天(下)

上下文Conversation Array 要让GPT记住上下文&#xff0c;实现GPT4里的连续对话功能&#xff0c;需要把以下内容存入conversation array中去。 NPC background storyuser input promptNPC anwser open AI API的JsonObject JSONObject是一种数据结构&#xff0c;可以理解为JSO…

【Linux 20】进程控制

文章目录 &#x1f308; 一、创建线程⭐ 1. 线程创建函数⭐ 3. 给线程传参⭐ 4. 创建多线程⭐ 5. 获取线程 ID &#x1f308; 二、终止线程⭐1. 使用 return 终止线程⭐ 2. 使用 pthread_exit 函数终止线程⭐ 3. 使用 pthread_cancel 函数终止线程 &#x1f308; 三、等待线程⭐…

企微无限群发:精准营销与合规边界的探索

在数字化营销日益成熟的今天&#xff0c;企业微信&#xff08;简称“企微”&#xff09;作为连接企业与客户的重要桥梁&#xff0c;其强大的群发功能成为了众多企业推广产品、传递信息、增强客户粘性的首选工具。然而&#xff0c;“企微无限群发”这一概念&#xff0c;在实际操…

2024.9.11(k8s环境搭建)

一、k8s环境搭建 编号主机名称ip配置1k8s-master192.168.8.1772k8s-node1192.168.8.1783k8s-node2192.168.8.168 1、免密登录 [rootk8s-master ~]# ssh-keygen [rootk8s-master ~]# ssh-copy-id root192.168.8.178 [rootk8s-master ~]# ssh-copy-id root192.168.8.168 2、3台…

【裸机装机系列】5.kali(ubuntu)-安装linux所需软件-中文输入法,浏览器,字体等等

如果你执行完上面步骤&#xff0c;那恭喜你&#xff0c;你可以正常使用了。 接下来是安装linux里常用的软件 1> apt方式安装的软件&#xff1a; sudo apt install -y terminator fcitx redshift-gtk dbeaver gwenview flameshot vlc mpv alsa-utils imagemagick lshw…

在安全验证流程中,风险评估与智能判断有以下具体应用:

一、用户行为分析 1. 登录模式识别 - 分析用户的登录时间、地点和设备信息。如果用户经常在特定的时间段、特定的地理位置以及固定的设备上登录&#xff0c;系统可以将其识别为低风险行为。例如&#xff0c;一个用户通常在晚上 7 点到 10 点之间&#xff0c;从家庭住址所在…