【问题标题】:Any way to link to the Android notification settings for my app?有什么方法可以链接到我的应用的 Android 通知设置?
【发布时间】:2015-11-28 18:11:58
【问题描述】:

我有什么方法可以启动一个 Intent 以访问我的应用程序的 Android 通知设置屏幕(如下图所示)?还是一种简单的方法,我可以制作一个 PreferenceScreen 项目,只需点击一下就可以到达这里?

【问题讨论】:

  • 看起来 Settings.ACTION_APPLICATION_DETAILS_SETTINGS 会让我进入主应用信息屏幕,但我正在尝试进一步进入应用信息屏幕上的通知设置...
  • 当我们在 @mohamed-hafez 时,您能解释一下您是如何在此处锚定此“应用程序设置”条目的吗?我认为这是通过清单中的意图过滤器完成的,但没有做到。谢谢!
  • @Gabriel,看起来您已经找到了问题的答案,但对于其他感兴趣的人,答案是 here
  • 如何打开应用通知类别(默认)?在奥利奥。我们可以在其中更改声音、振动和其他设置

标签: android android-notifications android-6.0-marshmallow


【解决方案1】:

Kotlin 编写的更新版本,包含此处描述的所有案例。

fun showNotificationSettings(context: Context, channelId: String? = null) {
    val notificationSettingsIntent = when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O /*26*/ -> Intent().apply {
            action = when (channelId) {
                null -> Settings.ACTION_APP_NOTIFICATION_SETTINGS
                else -> Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS
            }
            channelId?.let { putExtra(Settings.EXTRA_CHANNEL_ID, it) }
            putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P /*28*/) {
                flags += Intent.FLAG_ACTIVITY_NEW_TASK
            }
        }
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP /*21*/ -> Intent().apply {
            action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
            putExtra("app_package", context.packageName)
            putExtra("app_uid", context.applicationInfo.uid)
        }
        Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT /*19*/ -> Intent().apply {
            action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
            addCategory(Intent.CATEGORY_DEFAULT)
            data = Uri.parse("package:${context.packageName}")
        }
        else -> null
    }
    notificationSettingsIntent?.let(context::startActivity)
}

你可以这样使用它

showNotificationSettings(context)

或者您可以添加频道 ID 以显示频道设置

showNotificationSettings(context, channelId = "some_channel_id")

【讨论】:

    【解决方案2】:

    我想介绍一个(恕我直言)更简洁的@Helix 答案:

    fun openNotificationsSettings() {
        val intent = Intent()
        when {
            Build.VERSION.SDK_INT > Build.VERSION_CODES.O -> intent.setOpenSettingsForApiLarger25()
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> intent.setOpenSettingsForApiBetween21And25()
            else -> intent.setOpenSettingsForApiLess21()
        }
        app.startActivity(intent)
    }
    
    private fun Intent.setOpenSettingsForApiLarger25(){
        action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
        putExtra("android.provider.extra.APP_PACKAGE", app.packageName)
    }
    
    private fun Intent.setOpenSettingsForApiBetween21And25(){
        action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        putExtra("app_package", app.packageName)
        putExtra("app_uid", app.applicationInfo?.uid)
    }
    
    private fun Intent.setOpenSettingsForApiLess21(){
        action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        addCategory(Intent.CATEGORY_DEFAULT)
        data = Uri.parse("package:" + app.packageName)
    }
    

    当分支到一个紧凑的类时,可以更进一步并提取每个。并创建一个 when 所在的工厂。

    【讨论】:

    • "然后创建一个工厂..." 这就是让简单代码变得复杂的方法。
    • @Ridcully 好吧,回头回答我会 100% 同意。但我不会编辑,因为它对过度设计是一个很好的讽刺。
    【解决方案3】:

    对于懒人来说,这是@Helix 答案的 kotlin 版本:

    fun openAppNotificationSettings(context: Context) {
        val intent = Intent().apply {
            when {
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
                    action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
                    putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
                }
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> {
                    action = "android.settings.APP_NOTIFICATION_SETTINGS"
                    putExtra("app_package", context.packageName)
                    putExtra("app_uid", context.applicationInfo.uid)
                }
                else -> {
                    action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                    addCategory(Intent.CATEGORY_DEFAULT)
                    data = Uri.parse("package:" + context.packageName)
                }
            }
        }
        context.startActivity(intent)
    }
    

    【讨论】:

    • 有没有办法在不启动设置活动的情况下从应用程序内部处理推送通知设置?
    【解决方案4】:

    我合并了 Sergei 和 Shhp 的解决方案以支持所有情况:

        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
            intent.putExtra("app_package", context.getPackageName());
            intent.putExtra("app_uid", context.getApplicationInfo().uid);
        } else {
            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            intent.setData(Uri.parse("package:" + context.getPackageName()));
        }
        context.startActivity(intent);
    

    【讨论】:

      【解决方案5】:

      以下内容适用于 Android 5.0 (Lollipop) 及更高版本:

      Intent intent = new Intent();
      intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
      
      //for Android 5-7
      intent.putExtra("app_package", getPackageName());
      intent.putExtra("app_uid", getApplicationInfo().uid);
      
      // for Android 8 and above
      intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());
      
      startActivity(intent);
      

      注意:这在 Android 5-7 中不受官方支持,但它工作得很好。它从 Android 8 开始得到官方支持。此代码不向后兼容 5.0 之前的 Android 版本。

      【讨论】:

      • @shhp - 谢谢你的回答。也适用于 N 预览。请用几句话说一下您是如何找到这个解决方案的?我在这次调查中得到的最远的是这个日志消息:com.android.settings D/SubSettings: Launching fragment com.android.settings.notification.AppNotificationSettings 在应用程序设置中单击“通知”行时。 link2src
      • @Dev-iL 你迈出了第一步。然后我检查了源代码,看看应该在intent 中添加什么额外内容:-)
      • 这很酷,但用户应该注意一些事情:1)这个意图依赖于Settings应用程序的内部/隐藏代码,所以不能保证将来@987654328 @app 不会更改并且不再使用相同的字符串操作、组件或 Intent extras 来打开特定于应用程序的通知屏幕。 2) 这种方法不完全向后兼容。使用的 String 动作和组件是大约 2 年前引入的。 See commit here
      • @TonyChan 谢谢你的提醒。我会在答案中添加它们。
      • 附注:也可以到达具体的通知渠道设置,如下图:stackoverflow.com/a/48854197/878126
      【解决方案6】:

      我为 Android 8.0 Oreo API 26 或更高版本附加了频道通知设置。 Android 4.4 有一个解决方案,KitKat。

      频道通知设置的用途:

      // PRIMARY_CHANNEL:
      goToNotificationSettings(getString(R.string.PRIMARY_CHANNEL), mContext);
      // SECONDARY_CHANNEL:
      goToNotificationSettings(getString(R.string.SECONDARY_CHANNEL), mContext);
      

      应用通知设置的用途:

      goToNotificationSettings(null, mContext);
      

      goToNotificationSettings的方法:

      public void goToNotificationSettings(String channel, Context context) {
          Intent intent = new Intent();
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
              intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
              if (channel != null) {
                  intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
                  intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel);
              } else {
                  intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
              }
              intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
          } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
              if (channel != null) {
                  intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
                  intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel);
              } else {
                  intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
              }
              intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
          } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
              intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
              intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
          } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
              intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
              intent.putExtra("app_package", context.getPackageName());
              intent.putExtra("app_uid", context.getApplicationInfo().uid);
          } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
              intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
              intent.addCategory(Intent.CATEGORY_DEFAULT);
              intent.setData(Uri.parse("package:" + context.getPackageName()));
          }
          context.startActivity(intent);
      }
      

      【讨论】:

      • Settings.ACTION_APP_NOTIFICATION_SETTINGS 可从 API >= Build.VERSION_CODES.O 获得,因此不应在 N_MR1 developer.android.com/reference/android/provider/… 上使用它
      • if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) 中的代码永远不会被执行,在某些情况下您正确使用了Settings.ACTION_APP_NOTIFICATION_SETTINGS,但在其他一些情况下您使用的是硬编码字符串"android.settings.APP_NOTIFICATION_SETTINGS"
      【解决方案7】:

      我合并了上面一些答案的代码并添加了少量编辑,我已经测试并且它在 Android KitKat、Lollipop、Marshmallow、Nougat、Oreo 和 Pie,API 级别 19 - 28 上运行良好

      public void goToNotificationSettings(Context context) {
      
          String packageName = context.getPackageName();
      
          try {
              Intent intent = new Intent();
              if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
      
                  intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
                  intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
                  intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
      
              } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
      
                  intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
                  intent.putExtra("android.provider.extra.APP_PACKAGE", packageName);
      
              } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      
                  intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
                  intent.putExtra("app_package", packageName);
                  intent.putExtra("app_uid", context.getApplicationInfo().uid);
      
              } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
      
                  intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                  intent.addCategory(Intent.CATEGORY_DEFAULT);
                  intent.setData(Uri.parse("package:" + packageName));
      
              } else {
                  return;
              }
      
              startActivity(intent);
      
          } catch (Exception e) {
              // log goes here           
      
          }
      
      }
      

      【讨论】:

        【解决方案8】:

        最后我测试了几乎所有的设备并且工作正常。给出的代码如下

        public void goToPushSettingPage(Context context) {
            try {
                Intent intent=new Intent();
                if(Build.VERSION.SDK_INT>Build.VERSION_CODES.N_MR1){
                    intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
                    intent.putExtra(Settings.EXTRA_APP_PACKAGE,context.getPackageName());
                }else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
                    intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
                    intent.putExtra(ConstUtil.PUSH_SETTING_APP_PACKAGE,context.getPackageName());
                    intent.putExtra(ConstUtil.PUSH_SETTING_APP_UID,context.getApplicationInfo().uid);
                }else{
                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.setData(Uri.parse(ConstUtil.PUSH_SETTING_URI_PACKAGE+context.getPackageName()));
                }
                startActivity(intent);
            } catch (Exception e) {
                // log goes here
            }
        }
        

        【讨论】:

          【解决方案9】:

          使用ACTION_APP_NOTIFICATION_SETTINGS会列出应用的所有频道:

          Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
              .putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
          startActivity(intent);
          

          打开单通道设置,可以使用ACTION_CHANNEL_NOTIFICATION_SETTINGS

          您可以在其中更改各个频道的sound,vibration.etc 设置。

           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
           Intent intent = new Intent("android.settings.CHANNEL_NOTIFICATION_SETTINGS");
                  intent.putExtra("android.provider.extra.CHANNEL_ID", "ChannelID");
                  intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());
                  startActivity(intent);
             } 
          

          【讨论】:

            【解决方案10】:
            public static void goToNotificationSettings(Context context) {
                    Intent intent = new Intent();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        intent.setData(Uri.fromParts(SCHEME, context.getPackageName(), null));
                    } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
                        intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
                        intent.putExtra("app_package", context.getPackageName());
                    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
                        intent.putExtra("app_package", context.getPackageName());
                        intent.putExtra("app_uid", context.getApplicationInfo().uid);
                    } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
                        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        intent.addCategory(Intent.CATEGORY_DEFAULT);
                        intent.setData(Uri.parse("package:" + context.getPackageName()));
                    } else {
                        return;
                    }
                    context.startActivity(intent);
                }
            

            【讨论】:

            • 什么是 SCHEME 常数?
            • 看起来分支else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) 永远不会被调用
            【解决方案11】:

            我使用这个代码(kitkat 和下一个版本):

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Intent intent = new Intent();
                intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
                intent.putExtra("app_package", getActivity().getPackageName());
                intent.putExtra("app_uid", getActivity().getApplicationInfo().uid);
                startActivity(intent);
            } else if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                intent.addCategory(Intent.CATEGORY_DEFAULT);
                intent.setData(Uri.parse("package:" + getActivity().getPackageName()));
                startActivity(intent);
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-10-20
              • 1970-01-01
              • 1970-01-01
              • 2021-03-31
              相关资源
              最近更新 更多