Android 10(Q) 以上普通 APP 隐藏应用图标问题探究及解决方案

1、实验环境

aosp 版本 10.0 系统

aosp 版本 13.0 系统

2、验证结果

2.1 方式一

APP AndroidManifest.xml 中通过 activity-alias 配置带 LAUNCHER 属性 category,并且 android:enabled="true"

10.0 系统中可安装后正常显示 icon,通过 setComponentEnabledSetting 隐藏 icon 成功,桌面上不留下 app 相关任何图标

13.0 系统中可安装后正常显示 icon,通过 setComponentEnabledSetting 隐藏 icon 不成功,桌面上会留下透明占位 alias 图标

2.2 方式二

APP AndroidManifest.xml 中通过 activity-alias 配置带 LAUNCHER 属性 category,并且 android:enabled="false"

10.0 系统中首次安装后直接不显示 icon,但通过 setComponentEnabledSetting 可控制隐藏 icon 成功,桌面上不留下 app 相关任何图标

13.0 系统中首次安装后直接不显示 icon,但通过 setComponentEnabledSetting 可控制隐藏 icon 成功,桌面上不留下 app 相关任何图标

3、展开讲讲

目前隐藏图标的思路几乎都是这样的,在 AndroidManifest.xml 中配置一些 activity-alias,然后通过

getPackageManager().setComponentEnabledSetting(new ComponentName(con,activityAliasName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);

禁用(隐藏) activity-alias 组件

启用(显示) activity-alias 组件

在 10.0 以上高版本,谷歌加了补丁更新,导致此种方式不再适用。由这个值 show_hidden_icon_apps_enabled 控制

Settings.Global.putInt(getContentResolver(), "show_hidden_icon_apps_enabled", 0);

经过验证,将 show_hidden_icon_apps_enabled 改为 0,高版本上即可延用之前方式隐藏图标。

但普通app是肯定改不了这个值的,没有权限 Permission denial: writing to settings requires:android.permission.WRITE_SECURE_SETTINGS

更多解释可查看

那些年的Android开发经验记录
Android应用之隐藏桌面图标的一种方法
android 动态修改dimens android动态修改图标和名称

4、测试代码

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="cn.test.hideicon">

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/icon_transparent"
        android:label="@string/app_name"
        android:roundIcon="@drawable/ic_cloud"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--<activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>-->

        <activity
            android:name="cn.test.hideicon.AliasMainActivity"
            android:exported="true"
            android:theme="@style/KeepLiveTheme">
            <!-- <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
                 <data
                     android:host="MainActivity"
                     android:scheme="com.learn.alias.target"
                     tools:ignore="AppLinkUrlError" />
             </intent-filter>-->

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.TEST" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="com.ksgzlf.djbwrpgk" />

                <data android:host="goapp.fromchrome" android:scheme="tgsoft" />
            </intent-filter>
        </activity>

        <!-- 外部要启动的Activity -->
        <activity
            android:name="cn.test.hideicon.MainActivity"
            android:excludeFromRecents="true"
            android:exported="true"
            android:finishOnTaskLaunch="false"
            android:launchMode="singleInstance" />

 
        <activity
            android:name="cn.test.hideicon.AliasActivity"
            android:excludeFromRecents="true"
            android:exported="true"
            android:finishOnTaskLaunch="false"
            android:launchMode="singleInstance"
            android:theme="@style/TransparentStyle">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.TEST" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="com.ksgzlf.djbwrpgk" />
                <data android:host="goapp.fromchrome" android:scheme="tgsoft" />
            </intent-filter>
        </activity>


        <activity-alias
            android:name="cn.test.hideicon.Alias1Activity"
            android:enabled="true"
            android:exported="true"
            android:icon="@drawable/ic_launcher_background"
            android:label="aaaa"
            android:launchMode="singleTask"
            android:roundIcon="@drawable/icon_transparent"
            android:targetActivity="cn.test.hideicon.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
<!--                <category android:name="android.intent.category.BROWSABLE" />-->
<!--                <category android:name="android.intent.category.TEST" />-->
                <category android:name="android.intent.category.LAUNCHER" />
<!--                <category android:name="com.ksgzlf.djbwrpgk" />-->
<!--                <data android:host="goapp.fromchrome" android:scheme="tgsoft" />-->
            </intent-filter>
        </activity-alias>


        <activity-alias
            android:name="com.android.ui.ActivityAliasN"
            android:configChanges="keyboard|orientation|screenSize"
            android:enabled="false"
            android:exported="true"
            android:icon="@drawable/ic_launcher_background"
            android:label="bbbb"
            android:launchMode="singleTask"
            android:roundIcon="@drawable/icon_transparent"
            android:targetActivity="cn.test.hideicon.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity-alias>


        <activity-alias
            android:name="com.android.ui.ActivityAlias5"
            android:configChanges="keyboard|orientation|screenSize"
            android:enabled="true"
            android:exported="true"
            android:icon="@drawable/icon_transparent"
            android:label="maygroup55555"
            android:launchMode="singleTask"
            android:roundIcon="@drawable/icon_transparent"
            android:targetActivity="cn.test.hideicon.MainActivity">
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.CHOOSER" />
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.SEND" />
                <action android:name="android.intent.action.SEND_MULTIPLE" />

                <category android:name="android.intent.category.INFO" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="com.android.internal.category.PLATLOGO" />
                <category android:name="android.intent.category.BROWSABLE" />

                <action android:name="android.intent.action.PACKAGE_REMOVED" />
                <action android:name="android.intent.action.PACKAGE_REPLACED" />
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_CHANGED" />
                <action android:name="com.ui.OnAlarmReceiver.ACTION_WIDGET_RECEIVER" />
                <action android:name="com.android.vending.billing.InAppBillingService.COIN" />
                <action android:name="com.android.vending.billing.InAppBillingService.COIO" />
                <action android:name="com.android.vending.billing.InAppBillingService.LUCM" />
                <action android:name="com.android.vending.billing.InAppBillingService.PROX" />
                <action android:name="ir.cafebazaar.pardakht.InAppBillingService.BIND" />
                <action android:name="ru.aaaaaaax.installer" />
                <action android:name="com.nokia.payment.iapenabler.InAppBillingService.BIND" />
                <action android:name="com.android.vending.billing.InAppBillingService.INST" />
                <action android:name="com.App.Reborn" />
            </intent-filter>
        </activity-alias>
    </application>
</manifest>

MainActivity.java

java 复制代码
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //adb shell settings get global show_hidden_icon_apps_enabled
        try {
            int showHidden = Settings.Global.getInt(getContentResolver(),
                    "show_hidden_icon_apps_enabled", 1);
            Log.d("MainActivity", "showHidden: " + showHidden);
            if (showHidden != 0) {
                Settings.Global.putInt(getContentResolver(), "show_hidden_icon_apps_enabled", 0);
                Log.i("MainActivity", "set showHidden: ");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void show(View view) {
        String clazzName = "com.android.ui.ActivityAliasN";
        enableComponent(this, clazzName);
        enableComponent(this, "cn.test.hideicon.Alias1Activity");
        finish();
    }

    public void hide(View view) {
        String clazzName = "com.android.ui.ActivityAliasN";
        disableComponent(this, clazzName);
        disableComponent(this, "cn.test.hideicon.Alias1Activity");
        finish();
    }

    /**
     * 启动组件
     */
    public static void enableComponent(Context context, String clazzName) {
        ComponentName componentName = new ComponentName(context, clazzName);
        PackageManager mPackageManager = context.getPackageManager();
        mPackageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    }

    /**
     * 禁用组件
     */
    public static void disableComponent(Context context, String clazzName) {
        ComponentName componentName = new ComponentName(context, clazzName);
        PackageManager mPackageManager = context.getPackageManager();
        mPackageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
    }

}

AliasMainActivity.java

java 复制代码
public class AliasMainActivity extends AppCompatActivity {

    private Button toActivity, hideActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Window window = getWindow();
        window.setGravity(Gravity.LEFT | Gravity.TOP);
        WindowManager.LayoutParams params = window.getAttributes();
        params.x = 0;
        params.y = 0;
        params.width = 1;
        params.height = 1;
        window.setAttributes(params);
        finish();
    }

}
相关推荐
zhangphil31 分钟前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_5127446431 分钟前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.1 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao1 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee1 小时前
PHP伪协议总结
android·开发语言·php
mmsx8 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人11 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌12 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
_Shirley13 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙
hedalei15 小时前
RK3576 Android14编译OTA包提示java.lang.UnsupportedClassVersionError问题
android·android14·rk3576