多种方式实现动态替换Android默认桌面Launcher

多种方式实现动态替换Android默认桌面Launcher

背景简介

Launcher-是安卓系统中的桌面启动器,安卓系统的桌面UI统称为Launcher。Launcher是安卓系统中的主要程序组件之一,安卓系统中如果没有Launcher就无法启动Android

  • 当前场景
    现在安卓设备应用越来越广泛,有些出厂前可能没有预留系统OTA升级的入口,但是有app的升级通道,而又在一些情况下需要更改已经出厂的系统默认桌面,所以针对这种情况需要实现一种方案,在不进行系统升级更改的情况下,只通过升级App的方式,实现动态替换默认Launcher的方案

技术方案

三种方案

  • 用代码设置系统配置,保留两个Launcher应用进行动态切换

  • 动态删除添加系统默认/system/priv-app/目录下的默认Launcher.apk文件

  • 不设置Launcher,通过获取系统底层对Activity状态的监控,拦截Launcher

前三种方案都需要系统权限,并在AndroidManifest.xml 中配置Launcher属性

  • 系统权限,配置shareUserId,并且用系统签名文件进行签名
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
	    package="com.test.launcher"
	    android:sharedUserId="android.uid.system">
  • 新增Launcher属性
       <activity android:name=".MainActivity">
            <intent-filter>
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
 
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
      </acivity>
方案一

使用代码配置动态Launcher,需要额外的添加一个系统级别的权限

    <permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"/>

该权限允许应用程序,进行系统属性的配置更改,有了该权限后,才可以进行动态的属性配置。


清除默认Launcher:

  1. 安装运行自定义Launcher应用
  2. 遍历所有配置Launcher属性的应用
  3. 清除除所有应用Launcher属性
  4. 添加自定义桌面应用Launcher属性配置
    private void clear(Context context){
      
        ArrayList<IntentFilter> intentList = new ArrayList<>();
        ArrayList<ComponentName> cnList = new ArrayList<>();
        context.getPackageManager().getPreferredActivities(intentList, cnList, null);
        for(int i = 0; i < cnList.size(); i++) {
            IntentFilter dhIF = intentList.get(i);
            if(dhIF.hasAction(Intent.ACTION_MAIN) && dhIF.hasCategory(Intent.CATEGORY_HOME)) {//遍历过滤所有launcher
                try {
                    String name = cnList.get(i).getPackageName();
             //清除原有的默认launcher     
                         context.getPackageManager().clearPackagePreferredActivities(name;
                }catch (Exception ex){
                }
            }
        }
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MAIN);
        filter.addCategory(Intent.CATEGORY_HOME);
        filter.addCategory(Intent.CATEGORY_DEFAULT);

        final int N = mHome.size();
        ComponentName[] set = new ComponentName[N];
        for (int i = 0; i < N; i++) {
            ResolveInfo r = mHome.get(i);
            set[i] = new ComponentName(r.activityInfo.packageName,r.activityInfo.name);
        }
        //设置自定义launcher
        ComponentName launcher = new ComponentName(hiBoxLauncher, hiBoxActivity);
        context.getPackageManager().addPreferredActivity(filter, 1081344, set, launcher);
    }

恢复默认Launcher方法同上一样,清除完所有Launcher相关的意图配置,最后添加上系统Launcher包名。

方案二

通过文件删除的方式进行Launcher替换,需要文件的读写权限,而且系统应用删除后需要重启才能生效,所以还需要reboot的权限

    <permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <permission android:name="android.permission.REBOOT"/>

清除默认Launcher:

  1. 安装运行自定义Launcher应用
  2. 复制/system/priv-app/Launcher2.apk保存到sdcrad
  3. 删除/system/priv-app/Launcher2.apk
  4. 重启安卓系统,只留下自定义Launcher应用生效

恢复默认launcher只需要将事先保存的apk,拷贝到系统目录即可,当前系统会存在两个Launcher,需要手动选择一次默认Launcher

方案三

不需要替换Launcher,通过反射的方式注册系统android.app.
IActivityController的隐藏aidl回调。监听每个应用的Activity界面的状态,当回调系统显示Launcher的时候拦截回调,打开自定义的应用界面,覆盖系统Launcher,需要系统权限,还需要额外的Activity设置权限

    <uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER" />

1.声明aidl文件
在工程中声明一个android.app.IActivityController的aidl,用于注册系统的回调,可以直接从Android源码中拷贝


    interface IActivityController{
  
    boolean activityStarting(in Intent intent, String pkg);
    
    boolean activityResuming(String pkg);
    
    boolean appCrashed(String processName, int pid,
            String shortMsg, String longMsg,
            long timeMillis, String stackTrace);

    int appEarlyNotResponding(String processName, int pid, String annotation);

    int appNotResponding(String processName, int pid, String processStats);
}

2.反射注册aidl回调代码:


     //在进入页面时调用setActivityController()方法,注册aidl回调,当界面有变化时会触发activityStarting(),activityResuming()事件
    public void setActivityController() {
        Log.d(TAG,">>>>>>0519,");
        try {
            Class<?> cActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
            Method mGetDefault = cActivityManagerNative.getMethod("getDefault", new Class[]{});
            Object oActivityManagerNative = mGetDefault.invoke(null, new Object[]{});
            Method mSetActivityController = cActivityManagerNative.getMethod("setActivityController",
                    Class.forName("android.app.IActivityController"));
            mSetActivityController.invoke(oActivityManagerNative, new ActivityController());
        } catch (ClassNotFoundException e) {
            exceptionWhenSet(e);
        }

3.拦截Launcher
绑定服务,获取系统回调的Activity状态接口,进行应用打开操作

    private class ActivityController extends android.app.IActivityController.Stub {

        public boolean activityStarting(Intent intent, String pkg) {
            
            if(launcher2.equals(pkg)&&isFilter){
            startHiBoxLauncher();            }
            return true;
        }
        public boolean activityResuming(String pkg) {
            Log.d(TAG,">>>>>>0519,pkg=" + pkg);
            if(launcher2.equals(pkg)&&isFilter){
                startHiBoxLauncher();
            }
            return true;
        }
    }

如果是管理员进行操作,需要恢复Launcher,可以用过标志位Boolen值来控制是否拦截系统Launcher

风险

  • 1.重启安卓设备Launcher配置重置,方案一代码设置生效后,不需要手动进行选择,可以同时在两个launcher中切换,但是测试发现,安卓设备重启后,会清除配置,需要重新选择默认Launcher
    Launcher选择

  • 2.Android系统应用无法删除,在一些设备上测试发现,即使有了系统权限,只能对/system/priv-app/Launcher2.apk进行拷贝操作,无法进行删除操作。

  • 3.签名不一致覆盖安装风险,所有的方案都需要重新系统签名,获取系统权限,跟之前Android应用签名不一致,可能会出现覆盖安装失败的问题

Android设备的默认launcher设置是指系统默认的启动器(Launcher)应用程序。启动器是用户在设备上看到和操作的主屏幕,它提供了桌面、应用程序列表、小部件和壁纸等功能。 在Android设备上,不同的制造商可能会有不同的默认启动器设置,例如Samsung可能会有自己的启动器样式,而Google的Pixel设备则使用原生Android启动器。 默认启动器有以下几个主要特点和功能: 1. 桌面默认启动器会在设备主屏幕上显示桌面,用户可以在桌面上添加和管理应用程序、小部件和快捷方式等。 2. 应用程序列表:用户可以通过默认启动器访问设备上安装的所有应用程序的列表,并进行搜索和排序。 3. 小部件:默认启动器支持用户在桌面上添加各种小部件,例如天气、日历、音乐播放器等,以便用户更方便地获取相关信息。 4. 壁纸:默认启动器还允许用户更改桌面背景壁纸,可以选择自己喜欢的图片或者使用系统提供的预设壁纸。 对于用户来说,选择适合自己的默认启动器可以增加使用Android设备的个性化和便利性。用户可以根据自己的需求和偏好,选择不同功能和样式的启动器来进行设置。有些启动器还提供了更多的自定义选项,例如主题、图标包等,使用户能够将设备界面个性化到自己喜欢的样子。 总之,Android设备的默认启动器设置是一个重要的用户体验方面的设置选项,通过它可以实现设备主屏幕的个性化和功能拓展。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值