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的相关源码

 @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之后

一、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.mzph.cn/news/879651.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux使用Clash,clash-for-linux

文件下载 clash-for-linuxhttps://link.zhihu.com/?targethttps%3A//zywang.lanzn.com/ijE2a1m7h6mb&#xff08;百度和阿里云盘都不支持这个文件分享&#xff09;。 使用须知 - 此项目不提供任何订阅信息&#xff0c;请自行准备Clash订阅地址。 - 运行前请手动更改.env文件…

掌握ChatGPT:高效利用AI助手

2023 年 3 月 15 日&#xff0c;ChatGPT-4 的诞生标志着人类进入了一个全新的 人机协作时代。这个时代就像一个混沌初开的新世界&#xff0c;而 ChatGPT 则是这个新世界里诞生的一个新物种。 这个新物种的心智如同一个四五岁的小孩&#xff0c;在与它频繁互动中&#xff0c;人…

BFS 解决边权为1的最短路问题

文章目录 边权为1的最短路问题1926. 迷宫中离入口最近的出口题目解析算法原理代码实现 433. 最小基因变化题目解析算法原理代码实现 127. 单词接龙题目解析算法原理代码实现 675. 为高尔夫比赛砍树题目解析算法原理代码实现 边权为1的最短路问题 最短路问题&#xff1a; 比如…

Effective C++笔记之二十三:非void函数不写return

一.main函数 Qt Creator查看汇编的步骤如下 上图是g编译器下的汇编 eax就是main()函数的返回值 如果删掉return 0&#xff1b; 可以发现编译器还是把eax的值设为了0&#xff0c;由此可见&#xff0c;即使在main函数中不写return 0&#xff0c;编译器还是会默认添加个return 0。…

R语言统计分析——散点图2(散点图矩阵、高密度散点图)

参考资料&#xff1a;R语言实战【第2版】 1、散点图矩阵 pairs()函数可以创建基础的散点图矩阵。下面代码用于绘制一个散点图矩阵&#xff0c;包含mtcars数据集中的mpg、disp、drat和wt四个变量&#xff1a; pairs(~mpgdispdratwt,datamtcars,main"Basic Scatter Plot M…

太阳能光伏板航拍红外图像缺陷分类数据集

太阳能光伏板航拍红外图像缺陷分类数据集。 数据集共包含11种不同的缺陷分类&#xff0c; 总共20000张图片&#xff0c; 可用来做基于深度学习的缺陷分类 近红外&#xff0c;黑白图像&#xff0c;图示经过可视化处理。 数据集名称 太阳能光伏板缺陷分类数据集&#xff08;Sola…

三相可控整流电路 (三相半波,三相桥式)

目录 1. 三相半波整流电路 2. 三相桥式全控整流电路 三相可控整流电路利用三相交流电源&#xff0c;通过可控硅&#xff08;晶闸管&#xff09;将交流电整流为直流电。主要有两种常见类型&#xff1a;三相半波整流电路和三相桥式全控整流电路。 1. 三相半波整流电路 三相半波…

《沈阳体育学院学报》

《沈阳体育学院学报》创刊于1982年&#xff0c;是由沈阳体育学院主办&#xff0c;面向国内外公开发行的体育类学术期刊&#xff1b;国际标准刊号为ISSN 1004-0560&#xff0c;国内刊号为CN 21-1081/G8&#xff1b;双月刊&#xff0c;单月中旬出版。 《沈阳体育学院学报》是中文…

宝塔部署python项目

宝塔部署-python项目文章浏览阅读559次&#xff0c;点赞11次&#xff0c;收藏9次。在添加项目后&#xff0c;选择项目所在的路径&#xff0c;然后命令行启动主py文件。具体先看项目日志&#xff0c;根据日志在环境管理处下载包。首先下载项目需要的python版本。_宝塔部署python…

LabVIEW提高开发效率技巧----VI服务器和动态调用

VI服务器&#xff08;VI Server&#xff09;和动态调用是LabVIEW中的两个重要功能&#xff0c;可以有效提升程序的灵活性、模块化和可扩展性。通过这两者的结合&#xff0c;开发者可以在运行时动态加载和调用VI&#xff08;虚拟仪器&#xff09;&#xff0c;实现更为复杂的应用…

C++和OpenGL实现3D游戏编程【目录】

欢迎来到zhooyu的专栏。 个人主页&#xff1a;【zhooyu】 文章专栏&#xff1a;【OpenGL实现3D游戏编程】 贝塞尔曲面演示&#xff1a; 贝塞尔曲面演示zhooyu 本专栏内容&#xff1a; 我们从游戏的角度出发&#xff0c;用C去了解一下游戏中的功能都是怎么实现的。这一切还是要…

基于yolov8的无人机检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的无人机检测系统是一项前沿技术&#xff0c;结合了YOLOv8深度学习模型的强大目标检测能力与无人机的灵活性。YOLOv8作为YOLO系列的最新版本&#xff0c;在检测精度和速度上均有显著提升&#xff0c;特别适用于复杂和高动态的场景。 该系统通过捕获实…

论文笔记:基于LLM和多轮学习的漫画零样本角色识别与说话人预测

整理了ACM MM2024 Zero-Shot Character Identification and Speaker Prediction in Comics via Iterative Multimodal Fusion&#xff09;论文的阅读笔记 背景模型框架实现细节 实验数据集实验可视化消融实验 背景 最近读到一篇新文章&#xff0c;主要是做漫画中的零样本角色识…

pikachu下

CSRF(跨站请求伪造) CSRF(get) url变成了这样了&#xff0c;我们就可以新开个页面直接拿url去修改密码 http://pikachu-master/vul/csrf/csrfget/csrf_get_login.php?username1&password2&submitLogin CSRF(post&#xff09; 这里只是请求的方式不同&#xff0c;…

HC-SR04超声波传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 ultrasonic.h文件 ultrasonic.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 HC-SR04超声波传感器是通过发送和接收超声波&#xff0c;利用时间差和声音传播速度…

带你深入了解C语言指针(四)

目录 前言一、回调函数是什么&#xff1f;二、qsort使用1.什么是qsort2.qsort函数的语法解析3.回顾冒泡排序4.使用qsort函数排序整型数据4.1 思路分析4.2 完整代码&#xff1a;4.3 总体逻辑展现 5.使用qsort函数排序结构数据5.1 strcmp( )函数5.2 思路分析5.2.1 按名字比较5.2.…

力扣每日一题 公交站间的距离

环形公交路线上有 n 个站&#xff0c;按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离&#xff0c;distance[i] 表示编号为 i 的车站和编号为 (i 1) % n 的车站之间的距离。 环线上的公交车都可以按顺时针和逆时针的方向行驶。 返回乘客从出发点 start 到目…

C# 使用Socket通信,新建WinForm服务端、客户端程序

一、新建WinForm Socket服务端程序 注&#xff1a;rtbReceviceMsg为RichTextBox控件 服务端程序、界面 服务端代码 public partial class Form1 : Form {public Form1(){InitializeComponent();}public virtual void TriggerOnUpdateUI(string message){if (this.InvokeRequir…

Oracle发送邮件功能:配置自动化发信指南?

Oracle发送邮件服务设置方法&#xff1f;怎么用Oracle数据库发信&#xff1f; Oracle数据库作为企业级应用的核心&#xff0c;其内置的发送邮件功能为企业提供了强大的自动化工具。AokSend将详细介绍如何配置Oracle发送邮件功能&#xff0c;以实现自动化发信&#xff0c;从而提…

leetcode 2576.求出最多标记下标

2576.求出最多标记下标 题意&#xff1a; 解析&#xff1a; 数组长为 n n n&#xff0c;因为一次标记两个&#xff0c;所以数组中最多有 ⌊ n 2 ⌋ \lfloor \frac{n}{2}\rfloor ⌊2n​⌋ 对标记。 贪心的考虑&#xff0c;一个数 x 一定优先与满足 y ≥ 2 x y \ge 2x y≥2…