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、测试代码

    xmlns:tools="http://schemas.android.com/tools"

    package="cn.test.hideicon">

    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">

    android:name="cn.test.hideicon.AliasMainActivity"

    android:exported="true"

    android:theme="@style/KeepLiveTheme">

    android:name="cn.test.hideicon.MainActivity"

    android:excludeFromRecents="true"

    android:exported="true"

    android:finishOnTaskLaunch="false"

    android:launchMode="singleInstance" />

    android:name="cn.test.hideicon.AliasActivity"

    android:excludeFromRecents="true"

    android:exported="true"

    android:finishOnTaskLaunch="false"

    android:launchMode="singleInstance"

    android:theme="@style/TransparentStyle">

    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">

    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">

    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">

    MainActivity.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

    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();

    }

    }