文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android10 设置默认Launcher

2023-10-05 13:56

关注
  1. 不保留系统launcher
    在mk文件中添加这个属性LOCAL_OVERRIDES_PACKAGES := Launcher3 对应的mk中删除,不让其编译即可。
  2. 保留系统默认的Launcher

当系统存在多个launcher时,若没有设置默认launcher,开机启动后会弹出提示框,罗列所有launcher,用户选择并设置了默认launcher后,按home键以及以后重启都会进入默认的launcher。亦或者在设置--》应用和通知--》默认应用--》主屏幕应用 中也可设置默认launcher。

客户希望系统能直接就进入我设定的launcher而不是弹出框后选择然后设置

前提:客户的app需要有home属性

                

修改方法:

首先我们需要增加全局属性Settings.Global.DEFAULT_LAUNCHER,,客户可通过修改该属性设置自定义桌面

1:增加自定义属性://frameworks\base\core\java\android\provider\Settings.java  public static final class Global extends NameValueTable {        public static final String DEFAULT_LAUNCHER = "my_default_launcher";  }public static final class System extends NameValueTable {     public static final String DEFAULT_LAUNCHER = Global.DEFAULT_LAUNCHER;     PUBLIC_SETTINGS.add(DEFAULT_LAUNCHER);     MOVED_TO_GLOBAL.add(Settings.Global.DEFAULT_LAUNCHER);     }frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java private void loadGlobalSettings(SQLiteDatabase db) {      loadStringSetting(stmt, Settings.Global.DEFAULT_LAUNCHER,                    R.string.default_launcher); }               //frameworks\base\packages\SettingsProvider\res\values\defaults.xmlcom.android.launcher3/com.android.launcher3.Launcher

两种方法可选:

1:frameworks/base/core/java/com/android/internal/app/ResolverActivity.java 的configureContentView 读取设置的默认桌面,进行设置,mResolvingHome就是表示需要选择的是不是home在这里只针对home作处理。public boolean configureContentView(List payloadIntents, Intent[] initialIntents,        List rList) {  //....    if (rebuildCompleted) {        //....        //phoebe add for default launcher for prop Settings.Global.DEFAULT_LAUNCHER        if(mResolvingHome){               String defaultlauncher = Settings.Global.getString(getContentResolver(), Settings.Global.DEFAULT_LAUNCHER);        final TargetInfo defaultTarget = mAdapter.targetInfoForDefault(defaultlauncher);        Log.d(TAG, "zmm add for configureContentView:defaultlauncher:" + defaultlauncher + ":" + defaultTarget);        if (defaultTarget != null) {            safelyStartActivity(defaultTarget);            mPackageMonitor.unregister();            mRegistered = false;            finish();            return true;        }             }            }}2:在ResolveListAdapter 增加targetInfoForDefault方法,并且在rebuildList成功以后,再次设置默认laucnher    public class ResolveListAdapter extends BaseAdapter {        @Nullablepublic TargetInfo targetInfoForDefault(String info) {    if (TextUtils.isEmpty(info)) {        return null;    }    //com.yjx.inoexdash/com.yjx.inoexdash.ui.main.MainActivity    String[] namesArray = info.trim().split("/");    if (namesArray == null || namesArray.length < 2) {        return null;    }    String packageName = namesArray[0];    String activityInfo = namesArray[1];    if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(activityInfo)) {        return null;    }    ComponentName componentName = new ComponentName(packageName.trim(), activityInfo.trim());    Log.d(TAG, "zmm add for targetInfoForDefault:" + componentName + ":" + mDisplayList.size());    for (TargetInfo targetInfo : mDisplayList) {        ComponentName targetComponentName = targetInfo.getResolvedComponentName();        if (componentName.equals(targetComponentName)) {            return targetInfo;        }    }    return null;}    private void postListReadyRunnable() {    if (mPostListReadyRunnable == null) {        mPostListReadyRunnable = new Runnable() {            @Override            public void run() {                //phoebe add for default launcher for prop Settings.Global.DEFAULT_LAUNCHER               String defaultlauncher = mResolvingHome ? Settings.Global.getString(context.getContentResolver(), Settings.Global.DEFAULT_LAUNCHER) : null;                final TargetInfo defaultTarget = TextUtils.isEmpty(defaultlauncher) ? null : mAdapter.targetInfoForDefault(defaultlauncher);                Log.d(TAG, "zmm add for postListReadyRunnable defaultlauncher:" + defaultlauncher + ":" + defaultTarget);                if (defaultTarget != null) {                    safelyStartActivity(defaultTarget);                    finish();                    return;                }                setHeader();                resetButtonBar();                onListRebuilt();                mPostListReadyRunnable = null;            }        };        getMainThreadHandler().post(mPostListReadyRunnable);    }}}    

修改ActivityManagerService 跳过ResolverActivity

1:ActivityStartController 的startHomeActivity方法内读取用户设置的桌面,并且跳过Settings,和Provision因为第一次开机,会先Settings的CryptKeeper(加密),FallbackHome(设备正在启动中)接着是provision 的默认桌面,再是launcher3的Launcher页面zmm add for startHomeActivity...com.android.settings.CryptKeeper:ComponentInfo{com.android.settings/com.android.settings.CryptKeeper}   zmm add for startHomeActivity...com.android.settings.FallbackHome:ComponentInfo{com.android.settings/com.android.settings.FallbackHome}   zmm add for startHomeActivity...com.android.provision.DefaultActivity:ComponentInfo{com.android.provision/com.android.provision.DefaultActivity}    zmm add for startHomeActivity...com.android.launcher3.Launcher:ComponentInfo{com.android.launcher3/com.android.launcher3.Launcher}//frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.javavoid startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {        final ActivityOptions options = ActivityOptions.makeBasic();        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);        if (!ActivityRecord.isResolverActivity(aInfo.name)) {            // The resolver activity shouldn't be put in home stack because when the foreground is            // standard type activity, the resolver activity should be put on the top of current            // foreground instead of bring home stack to front.            options.setLaunchActivityType(ACTIVITY_TYPE_HOME);        }        //phoebe add for default launcher for prop Settings.Global.DEFAULT_LAUNCHER skip settings,Provision        String shortName = (intent == null || intent.getComponent() == null) ? null : intent.getComponent().getPackageName();        if (!isSettingsApp(shortName) && !isProvisionApp(shortName) && setTargetActivityAsPreferredActivity()) {            //Slog.d(TAG, " zmm add for  startHomeActivity as user seetings..");            return;        }         //phoebe add for default launcher for prop Settings.Global.DEFAULT_LAUNCHER skip settings,Provision end       ...    }//判断是不是Settings app    private boolean isSettingsApp(String shortName) {        return shortName != null && shortName.equals("com.android.settings");    }//判断是不是Provision app    private boolean isProvisionApp(String shortName) {        return shortName != null && shortName.equals("com.android.provision");    }//设置用户设置的桌面    private boolean setTargetActivityAsPreferredActivity() {        boolean result = false;        Context context = mService.mContext;        if (context == null)            return result;        String info = Settings.Global.getString(context.getContentResolver(), Settings.Global.DEFAULT_LAUNCHER);        Slog.d(TAG, " zmm add for  setTargetActivityAsPreferredActivity info=" + info);        if (TextUtils.isEmpty(info)) {            return result;        }        String[] namesArray = info.split("/");        if (namesArray == null || namesArray.length < 2) {            return result;        }        String packageName = namesArray[0];        String activityInfo = namesArray[1];        if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(activityInfo)) {            return result;        }        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);        packageName = packageName.trim();        activityInfo = activityInfo.trim();        PackageManager pm = context.getPackageManager();        List list = pm.queryIntentActivities(intent, 0);        final int N = list == null ? 0 : list.size();        ComponentName[] set = new ComponentName[N];        ComponentName componentName = null;        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;            if (packageName.equals(r.activityInfo.packageName) && activityInfo.equals(r.activityInfo.name)) {                 componentName = set[i];            }        }//        Slog.e(TAG, "zmm add for setTargetActivityAsPreferredActivity newcomponentName=" + componentName);        if (null != componentName) {            pm.replacePreferredActivity(filter, IntentFilter.MATCH_CATEGORY_EMPTY, set, componentName);            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            context.startActivity(intent);            result = true;        }        return result;    }2:接着修改frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,需要把用户在设置--》默认应用中选择的桌面应用保存到自定义的属性中。ComponentName getHomeActivitiesAsUser(List allHomeCandidates,            int userId) {      ...        for (int i = 0; i < resolveInfosSize; i++) {            ResolveInfo resolveInfo = resolveInfos.get(i);            if (resolveInfo.activityInfo != null && TextUtils.equals(                    resolveInfo.activityInfo.packageName, packageName)) {                        //phoebe add start                ComponentName componentName = new ComponentName(resolveInfo.activityInfo.packageName,                        resolveInfo.activityInfo.name);                Slog.d(TAG, "zmm add for getHomeActivitiesAsUser:com:"+componentName);                String value = resolveInfo.activityInfo.packageName + "/" + resolveInfo.activityInfo.name;                android.provider.Settings.Global.putString(mContext.getContentResolver(),                        android.provider.Settings.Global.DEFAULT_LAUNCHER, value);                        //phoebe add end                return componentName;            }        }        return null;    }

以上两种都可实现根据用户配置切换默认launcher

1:adb  切换adb shell settings put global my_default_launcher com.android.launcher3/com.android.launcher3.Launcher2:app可如此调用:Settings.Global.putString(getContentResolver(), "my_default_launcher", "com.yjx.inoexdash/com.yjx.inoexdash.ui.main.MainActivity");

客户的app如果是普通的三方app,设置Global属性可能是报错没有权限:

Settings.Global.putString(getContentResolver(), "my_default_launcher", "com.yjx.inoexdash/com.yjx.inoexdash.ui.main.MainActivity");报错:缺少权限:Manifest.permission.WRITE_SECURE_SETTINGS该权限是系统app才能申请的权限,普通app申请不到的话,我们可以去掉该限制。diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1249,18 +1250,23 @@ public class SettingsProvider extends ContentProvider {     private boolean mutateGlobalSetting(String name, String value, String tag,             boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,             int mode) {-        // Make sure the caller can change the settings - treated as secure. -       enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);                         String pkg = "com.android.settings"; //数据写入时使用系统settings应用的包名,系统会进行调用进程的包名判断         if(!"my_default_launcher".equals(name)){  //phoebe add 自定义数据不进行权限验证              pkg = "";              // Make sure the caller can change the settings - treated as secure.              enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);            }//下面修改在插入操作时使用上面预设的包名,绕过包名验证@@ -1268,7 +1274,7 @@ public class SettingsProvider extends ContentProvider {                 case MUTATION_OPERATION_INSERT: {                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM, name, value, tag, makeDefault,-getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);+"".equals(pkg)?getCallingPackage():pkg, forceNotify,  CRITICAL_GLOBAL_SETTINGS);                 }

每日语录:滴水穿石!!!加油!!!

单曲循环《如愿》

来源地址:https://blog.csdn.net/androidzmm/article/details/128285753

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯