【问题标题】:How to check if my app is allowed to show notification如何检查我的应用是否允许显示通知
【发布时间】:2015-01-07 09:04:36
【问题描述】:

在 Android 设置中,用户可以根据自己的意愿关闭通知。那么有没有像isNotificationAllowed() 这样的方法来检查我的应用程序是否允许显示通知?以及如何打开android设置页面来引导我的用户打开通知?

【问题讨论】:

标签: android notifications android-notifications


【解决方案1】:

编辑 - 新答案:

似乎谷歌添加了正确的 API 调用: NotificationManagerCompat.from(context).areNotificationsEnabled()


旧答案:

对于正在查看此问题的任何人,请注意 NotificationListenerService 与“显示通知”不同。 这两个是不同的东西!如果一个应用程序可以访问NotificationListenerService 并不意味着它的通知会显示,反之亦然。为了检查用户是否阻止了来自您的应用的通知,您可以使用反射:

public class NotificationsUtils {

private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

public static boolean isNotificationEnabled() {

    AppOpsManager mAppOps = (AppOpsManager) GlobalContext.getContext().getSystemService(Context.APP_OPS_SERVICE);

    ApplicationInfo appInfo = GlobalContext.getContext().getApplicationInfo();

    String pkg = GlobalContext.getContext().getApplicationContext().getPackageName();

    int uid = appInfo.uid;

    Class appOpsClass = null; /* Context.APP_OPS_MANAGER */

    try {

        appOpsClass = Class.forName(AppOpsManager.class.getName());

        Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class);

        Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
        int value = (int)opPostNotificationValue.get(Integer.class);

        return ((int)checkOpNoThrowMethod.invoke(mAppOps,value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return false;
}
}

来源:https://code.google.com/p/android/issues/detail?id=38482

【讨论】:

  • AppOpsManager 是在 API 级别 19 (Android 4.4) 中添加的,因此只能用于 API 级别 19+
  • @nibarius 是的,你是对的。但是:从 4.4 开始,用户可以在应用级别终止通知。因此在 4.4 以下,可以安全地假设通知已启用(除非在被篡改的 ROM 上运行)
  • @Kasra 我刚刚用运行 Android 4.2.2 的三星 Galaxy Grand 进行了测试,我也可以在那里终止应用程序级别的通知。这个 SO question 还说它可以在 4.1 的应用程序级别上完成:stackoverflow.com/questions/11649151/…
  • @nibarius 我的错。 4.1-4.4 是事情变得有点模糊的地方。请参阅我更新的答案。如果您查看 NotificationManagerCompat.from(context).areNotificationsEnabled() 的源代码,您会发现它对每个 android 版本使用不同的逻辑(它在内部也使用 AppOpsManager)。无论如何,这应该是最可靠的方式,因为它是由android团队制作的。
  • 嗨@kasra,这个方法比Android 8工作得好。但是这个方法在最新的android-8(Android - Oreo)中总是返回true。
【解决方案2】:
NotificationManagerCompat.from(context).areNotificationsEnabled()

似乎是一条路。

【讨论】:

  • 我通过手动更改设置中的通知权限对此进行了测试,效果很好,两种情况下都正确返回了布尔值。伟大的单线解决方案。并且及时..我在发布这个答案几个小时后才开始寻找解决方案..时机很好:)谢谢!
  • @gnB 不错!很高兴它有帮助;)
  • NotificationManagerCompat.From(context).AreNotificationsEnabled();
【解决方案3】:

这里是这个问题的更完整答案

fun areNotificationsEnabled(context: Context, channelId: String = "fcm_fallback_notification_channel"): Boolean {
    // check if global notification switch is ON or OFF
    if (NotificationManagerCompat.from(context).areNotificationsEnabled())
        // if its ON then we need to check for individual channels in OREO
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val channel = manager.getNotificationChannel(channelId)
            return channel?.importance != NotificationManager.IMPORTANCE_NONE
        } else {
            // if this less then OREO it means that notifications are enabled
            true
        }
    // if this is less then OREO it means that notifications are disabled
    return false
}

【讨论】:

    【解决方案4】:

    【讨论】:

    • 这是给NotificationListenerService的,和SHOW NOTIFICATION不同!!!
    【解决方案5】:

    试试这个:

    if (Settings.Secure.getString(getActivity().getContentResolver(), "enabled_notification_listeners").contains(getActivity().getPackageName())) {
        // Notification access service already enabled
        Toast.makeText(getActivity(),"notification enabled",Toast.LENGTH_LONG).show();
    } else {
        Intent intent = new Intent();
        intent.setClassName("com.android.settings", "com.android.settings.Settings$AppNotificationSettingsActivity");
        intent.putExtra("app_package", getPackageName());
        intent.putExtra("app_uid", getApplicationInfo().uid);
        startActivity(intent);
    }
    

    【讨论】:

    • 这是给NotificationListenerService的,和SHOW NOTIFICATION不同!!!
    【解决方案6】:
    if(NotificationManagerCompat.from(context).areNotificationsEnabled())
    {
     //Do your Work
    }
    else
    {
         //Ask for permission
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-18
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 2014-10-14
      • 1970-01-01
      相关资源
      最近更新 更多