当前位置: 首页 > news >正文

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

相关文章:

Android 源码多个Launcher设置默认Launcher

目录 第一部分、android10之前 一.多个launcher 启动设置默认launcher的核心类 二 在自定义服务里面设置默认Launcher 第二部分、android10之后 一、Launcher应用内置并设置为默认Launcher 1.通过ResolverActivity.java设置为默认Launcher 改法一&#xff1a; 改法二&am…...

计算机毕业设计 网上体育商城系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

深度学习中实验、观察与思考的方法与技巧

在深度学习中&#xff0c;实验、观察与思考是理解和改进模型性能的关键环节。以下是一些有效的方法与技巧&#xff0c;可以帮助你在深度学习实践中系统性地开展实验、分析结果并进行深入思考&#xff1a; 1. 明确实验目标 在开始实验前&#xff0c;确保对实验的目标有清晰的定…...

记一次 FastDFS 存储节点迁移:基于 scp 的实践与经验分享

一、背景 某某项目&#xff0c;机房到期&#xff0c;需要迁移至其他机房&#xff1b; 此项目已经运行了3年多&#xff0c;fastdfs累计数据大概在250G 左右&#xff0c;现需要把旧的fastdfs数据迁移到新的fastdfs上&#xff1b; 采用scp物理迁移数据的方式&#xff0c;停机迁移…...

http连接github远程仓库密码问题解决办法

目录 一、问题&#xff1a;使用http连接失败 二、解决办法&#xff1a;使用个人访问令牌。 1、生成访问令牌&#xff1a; 步骤 1: 登录 GitHub 步骤 2: 进入设置页面 步骤 3: 生成新的访问令牌 步骤 4: 配置访问令牌 步骤 5: 复制令牌 2. 使用访问令牌 一、问题&#…...

LAMP环境下项目部署

目录 目录 1、创建一台虚拟机 centos 源的配置 备份源 修改源 重新加载缓存 安装软件 2、关闭防火墙和selinux 查看防火墙状态 关闭防火墙 查看SELinux的状态 临时关闭SELinux 永久关闭SELinux&#xff1a;编辑SELinux的配置文件 配置文件的修改内容 3、检查系统…...

Visual Studio 2022从外部引入dll导致的问题

这里以我学MapGIS二次开发的一个小demo为例 一、如何引入dll 1、在解决方案资源管理器中&#xff0c;有个引用的选项 2、然后右键点击添加引用 点击之后会出现如下&#xff1a; 3、点击浏览选项&#xff0c;选择想要引入dll的路径&#xff0c;这里我选择下载MapGIS 10的路径 …...

大模型从失败中学习 —— 微调大模型以提升Agent性能

人工智能咨询培训老师叶梓 转载标明出处 以往的研究在微调LLMs作为Agent时&#xff0c;通常只使用成功的交互轨迹&#xff0c;而丢弃了未完成任务的轨迹。这不仅造成了数据和资源的浪费&#xff0c;也可能限制了微调过程中可能的优化路径。论文《Learning From Failure: Integ…...

10.web应用体系以及windows网络常见操作应用

一、Dos命令 1.启动方式&#xff1a;winR&#xff0c;输入cmd 2.切换盘符/路径&#xff1a;盘符名称&#xff1a; &#xff08;C:) cd 目录 &#xff08;cd B111&#xff09;&#xff08;目录名按table键自动补全&#xff09; 3.查看目录&#xff1a;dir dir /p 分页展示目录及…...

【数据结构与算法 | 灵神题单 | 前后指针(链表)篇】力扣19, 61,1721

1. 力扣19&#xff1a;删除链表的倒数第N个节点 1.1 题目&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; …...

机器学习之实战篇——MNIST手写数字0~9识别(全连接神经网络模型)

机器学习之实战篇——Mnist手写数字0~9识别&#xff08;全连接神经网络模型&#xff09; 文章传送MNIST数据集介绍&#xff1a;实验过程实验环境导入模块导入MNIST数据集创建神经网络模型进行训练&#xff0c;测试&#xff0c;评估模型优化 文章传送 机器学习之监督学习&#…...

ICLR2024: 大视觉语言模型中对象幻觉的分析和缓解

https://arxiv.org/pdf/2310.00754 https://github.com/YiyangZhou/LURE 背景 对象幻觉&#xff1a;生成包含图像中实际不存在的对象的描述 早期的工作试图通过跨不同模式执行细粒度对齐&#xff08;Biten et al.&#xff0c;2022&#xff09;或通过数据增强减少对象共现模…...

数据库系统 第54节 数据库优化器

数据库优化器是数据库管理系统&#xff08;DBMS&#xff09;中的一个关键组件&#xff0c;它的作用是分析用户的查询请求&#xff0c;并生成一个高效的执行计划。这个执行计划定义了如何访问数据和执行操作&#xff0c;以最小化查询的执行时间和资源消耗。以下是数据库优化器的…...

微服务杂谈

几个概念 还是第一次听说Spring Cloud Alibaba &#xff0c;真是孤陋寡闻了&#xff0c;以前只知道 SpringCloud 是为了搭建微服务的&#xff0c;spring boot 则是快速创建一个项目&#xff0c;也可以是一个微服务 。那么SpringCloud 和 Spring boot 有什么区别呢&#xff1f;S…...

【Pandas操作2】groupby函数、pivot_table函数、数据运算(map和apply)、重复值清洗、异常值清洗、缺失值处理

1 数据清洗 #### 概述数据清洗是指对原始数据进行处理和转换&#xff0c;以去除无效、重复、缺失或错误的数据&#xff0c;使数据符合分析的要求。#### 作用和意义- 提高数据质量&#xff1a;- 通过数据清洗&#xff0c;数据质量得到提升&#xff0c;减少错误分析和错误决策。…...

如何分辨IP地址是否能够正常使用

在互联网的日常使用中&#xff0c;无论是进行网络测试、网站访问、数据抓取还是远程访问&#xff0c;一个正常工作的IP地址都是必不可少的。然而&#xff0c;由于各种原因&#xff0c;IP地址可能无法正常使用&#xff0c;如被封禁、网络连接问题或配置错误等。本文将详细介绍如…...

Sqoop 数据迁移

Sqoop 数据迁移 一、Sqoop 概述二、Sqoop 优势三、Sqoop 的架构与工作机制四、Sqoop Import 流程五、Sqoop Export 流程六、Sqoop 安装部署6.1 下载解压6.2 修改 Sqoop 配置文件6.3 配置 Sqoop 环境变量6.4 添加 MySQL 驱动包6.5 测试运行 Sqoop6.5.1 查看Sqoop命令语法6.5.2 测…...

【数据结构】排序算法系列——希尔排序(附源码+图解)

希尔排序 算法思想 希尔排序&#xff08;Shell Sort&#xff09;是一种改进的插入排序算法&#xff0c;希尔排序的创造者Donald Shell想出了这个极具创造力的改进。其时间复杂度取决于步长序列&#xff08;gap&#xff09;的选择。我们在插入排序中&#xff0c;会发现是对整体…...

c++(继承、模板进阶)

一、模板进阶 1、非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中…...

【机器学习】从零开始理解深度学习——揭开神经网络的神秘面纱

1. 引言 随着技术的飞速发展,人工智能(AI)已从学术研究的实验室走向现实应用的舞台,成为推动现代社会变革的核心动力之一。而在这一进程中,深度学习(Deep Learning)因其在大规模数据处理和复杂问题求解中的卓越表现,迅速崛起为人工智能的最前沿技术。深度学习的核心是…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...