【问题标题】:Android hide/unhide app icon programmaticallyAndroid以编程方式隐藏/取消隐藏应用程序图标
【发布时间】:2013-10-07 12:14:07
【问题描述】:

我使用下面的代码以编程方式隐藏应用程序图标

try{
    PackageManager p = getPackageManager();
    p.setComponentEnabledSetting(getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}catch (Exception e) {
    e.printStackTrace();
}

现在我想以编程方式使图标可见

【问题讨论】:

  • 我一直在寻找这个,但是我需要在哪里编写这段代码?
  • 如何动态传递包名并在设备中隐藏特定的应用图标

标签: android android-package-managers


【解决方案1】:

使用以下代码隐藏应用程序的图标:

PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class); // activity which is first time open in manifiest file which is declare as <category android:name="android.intent.category.LAUNCHER" />
p.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

这是恢复应用图标的方法。

PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);

重要修改:

根据docs,从 Android Q (API 29) 开始,无论如何,所有应用程序图标都将在启动器中可见,除非:

从 Android Q 开始,至少有一个应用的 Activity 或合成的 活动出现在返回的列表中,除非应用满足 至少满足以下条件之一:

  • 该应用是系统应用。
  • 该应用不请求任何权限。
  • 应用清单中的标签不包含任何代表应用组件的子元素。

此外,系统会隐藏部分或全部的合成活动 以下企业相关案例中的应用:

  • 如果设备是完全托管的设备,则返回的列表中不会出现任何应用的合成活动。
  • 如果当前用户有工作资料,则返回的列表中不会显示用户工作应用的合成活动。

【讨论】:

  • 您好,您的代码运行良好,但我有一件棘手的事情要做。隐藏图标后,如果用户拨打#007 等特定号码,我想启动该应用程序。我已经实现了拨出电话接收器并匹配我试图开始我的主要活动的号码,但它给了我 ActivityNotFoundException。如果你有任何想法,你能帮我吗..
  • @Scorpion 是的,您说得对,这将破坏您的活动,您无法访问该活动。为此,您需要使用另一种方式。
  • @Scorpion 对于这个问题我进行了大约 2 天的研发.. 是的,现在只需给你解决方案,一旦你隐藏它,你将隐藏你的 mainActivity 活动将不会被发现它被破坏,所以你需要要创建与 mainActivity2 相同的另一个活动,并且您需要将布尔值存储到 sharerdprefrence 以表明图标是否隐藏然后您需要打开 mainActivity2 否则 MainActivity ...请检查它
  • 您提出的相同要求是您的解决方案有效。但应用程序图标会继续显示,直到重新启动。有什么解决办法吗?? @CoronaPintu
  • 我知道它被问到已经有一段时间了,但我认为应该有另一个活动,没有用启动器意图过滤器定义(所以它不会出现在应用程序启动器中)拨出呼叫意图过滤器以启用主要活动。
【解决方案2】:

从您可以使用的启动器中隐藏应用程序图标的最佳方法

&lt;category android:name="android.intent.category.LEANBACK_LAUNCHER"/&gt;

在您的清单 MainActivity 中

  <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
        </intent-filter>
    </activity>

还在Manifest标签中添加uses-feature

<uses-feature
    android:name="android.software.leanback"
    android:required="true" />

【讨论】:

  • 对于其他以前的解决方案,这绝对是最好的和干净的解决方案。非常感谢
  • 是电视应用专用
  • 有什么方法可以手动处理? @Ahmad 是的,它运行良好,但我没有找到任何手动处理此问题的方法。 – Nwawel A Iroume 你实现了吗?请指教。坚持了很多天
  • @RaRa 我正在使用 Java 代码隐藏图标,但在 Android 10 上只有我的代码不起作用。
  • 怎么打开?
【解决方案3】:

要隐藏图标,请使用:

PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class); 
p.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

并取消隐藏图标:

PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);

重要提示: 如果您需要在隐藏时对应用程序中的主要活动执行某些操作,这会有点棘手。你将面对ActivityNotFoundException。要使其正常工作,您应该在对主要活动进行任何操作之前取消隐藏图标,并在完成后再次隐藏它。
简单的步骤: 此处收到 1 个电话
2-取消隐藏图标
3-启动主要活动
4-在主要活动上做你的事情
5-再次隐藏图标

【讨论】:

  • 这与一年前发布的代码有何不同?你的建议不应该是对此的评论吗?
  • @AbandonedCart 我的回答还提供了在禁用 MainActivity 时如何使用它。当您按照这种方法隐藏您的应用程序时,很有可能获得 ActivityNotFoundException,但没有一个答案没有关于它的详细信息。这就是为什么我将我的答案添加为新的,以便人们可以看到它。
  • 问题是应用隐藏后如何取消隐藏。答案的唯一原始部分似乎是一种与问题并不真正相关的方法,因为 OP 并没有询问他们在隐藏时尝试使用它会得到什么错误,而是如何取消隐藏它(通过解决错误默认)。应该是评论。
【解决方案4】:

从这里下载源代码 (Hide and Unhide the app icon in android programmatically)

MainActivity.java:

package com.deepshikha.hideappicon;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button btn_hide;
    private static final ComponentName LAUNCHER_COMPONENT_NAME = new ComponentName(
            "com.deepshikha.hideappicon", "com.deepshikha.hideappicon.Launcher");

    public static int REQUEST_PERMISSIONS = 1;
    boolean boolean_permission;
    ProgressDialog progressDialog;

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

    private void init() {
        btn_hide = (Button) findViewById(R.id.btn_hide);
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setTitle("Alert");
        progressDialog.setMessage("Please wait");


        if (isLauncherIconVisible()) {
            btn_hide.setText("Hide");
        } else {
            btn_hide.setText("Unhide");
        }


    }

    private void listener() {
        btn_hide.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_hide:

                progressDialog.show();
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        progressDialog.dismiss();
                        if (isLauncherIconVisible()) {
                            btn_hide.setText("Hide");
                        } else {
                            btn_hide.setText("Unhide");
                        }
                    }
                }, 10000);


                if (boolean_permission) {

                    if (isLauncherIconVisible()) {
                        fn_hideicon();
                    } else {
                        fn_unhide();
                    }
                } else {
                    Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show();
                }
                break;

        }

    }

    private boolean isLauncherIconVisible() {
        int enabledSetting = getPackageManager().getComponentEnabledSetting(LAUNCHER_COMPONENT_NAME);
        return enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
    }

    private void fn_hideicon() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Important!");
        builder.setMessage("To launch the app again, dial phone number 1234567890");
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                getPackageManager().setComponentEnabledSetting(LAUNCHER_COMPONENT_NAME,
                        PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                        PackageManager.DONT_KILL_APP);
            }
        });
        builder.setIcon(android.R.drawable.ic_dialog_alert);
        builder.show();
    }

    private void fn_unhide() {
        PackageManager p = getPackageManager();
        ComponentName componentName = new ComponentName(this, com.deepshikha.hideappicon.MainActivity.class);
        p.setComponentEnabledSetting(LAUNCHER_COMPONENT_NAME, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    }

    private void fn_permission() {
        if ((ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.PROCESS_OUTGOING_CALLS) != PackageManager.PERMISSION_GRANTED) ||
                (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.PROCESS_OUTGOING_CALLS) != PackageManager.PERMISSION_GRANTED)) {

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.PROCESS_OUTGOING_CALLS))) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.PROCESS_OUTGOING_CALLS},
                        REQUEST_PERMISSIONS);

            }

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.PROCESS_OUTGOING_CALLS))) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.PROCESS_OUTGOING_CALLS},
                        REQUEST_PERMISSIONS);

            }
        } else {
            boolean_permission = true;


        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSIONS) {

            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                boolean_permission = true;


            } else {
                Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show();

            }
        }
    }
}

LaunchAppReceiver.java:

package com.deepshikha.hideappicon;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;

/**
 * Created by deepshikha on 9/6/17.
 */

public class LaunchAppReceiver extends BroadcastReceiver {
    String LAUNCHER_NUMBER = "1234567890";
    private static final ComponentName LAUNCHER_COMPONENT_NAME = new ComponentName(
            "com.deepshikha.hideappicon", "com.deepshikha.hideappicon.Launcher");

    @Override
    public void onReceive(Context context, Intent intent) {
        String phoneNubmer = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        if (LAUNCHER_NUMBER.equals(phoneNubmer)) {
            setResultData(null);

            if (isLauncherIconVisible(context)) {

            } else {
                Intent appIntent = new Intent(context, MainActivity.class);
                appIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(appIntent);
            }


        }

    }

    private boolean isLauncherIconVisible(Context context) {
        int enabledSetting = context.getPackageManager().getComponentEnabledSetting(LAUNCHER_COMPONENT_NAME);
        return enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
    }

}

谢谢!

【讨论】:

    【解决方案5】:

    自 Android Q (API 29) 起不再支持此功能。详细信息也已添加到a previous answer。除非满足docs 中所述的以下条件之一,否则您的应用图标将可见:

    • 该应用程序是系统应用程序。
    • 该应用不请求任何权限。
    • 应用清单中的标签不包含任何子元素 表示应用组件。

    【讨论】:

      【解决方案6】:

      这是我迄今为止发现的,不幸的是它不是原始问题的答案,只是替代品

      1. 这是第一个选项,但如果您的应用程序需要权限并且不再有用(至少在 Android 10 中),正如 @CoronaPintu 在这里提到的 https://stackoverflow.com/a/22754642/1712446 这种方法有效但有很多限制

        private void hideIcon(Context context, Class activityToHide) {
            PackageManager packageManager = getPackageManager();
            ComponentName componentName = new ComponentName(context, activityToHide);
            packageManager.setComponentEnabledSetting(
                componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
        }
        
      2. 使用上述相同的方法加上 adb 命令,即使您的应用程序需要权限,此替代方法也可以使用,但您必须有权访问设备并连接到电脑,然后运行此命令

        隐藏: $adb shell settings put global show_hidden_icon_apps_enabled 0

        显示: $adb shell settings put global show_hidden_icon_apps_enabled 1

      以防万一,您无法从应用程序运行此命令

      1. 另一个选项是 DevicePolicyManager

        private void hideIcon(Context context, Class activityToHide) {
            ComponentName componentName = new ComponentName(context, activityToHide);
                DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getSystemService(getApplicationContext().DEVICE_POLICY_SERVICE);
                devicePolicyManager.setApplicationHidden(componentName, "your.package.name.here", true);
        }
        

      此方法有效,但同样我们有一些限制,您需要 启用设备所有者模式,您可以找到更多信息here

      要启用此模式,您必须运行此 adb 命令

      adb shell dpm set-device-owner my.package.name/.DevAdminReceiver
      

      但是您可以从应用程序中执行此命令

      Runtime.getRuntime().exec("dpm set-device-owner my.package.name/.DevAdminReceiver");    
      

      但是,如果手机已经设置了账号,这个方法会失败并出现下一个错误:

      java.lang.IllegalStateException: Not allowed to set the device owner because there are already several users on the device
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-26
        • 2011-05-13
        • 2018-11-17
        • 2012-01-13
        • 2011-12-29
        相关资源
        最近更新 更多