【问题标题】:In Android 7 (API level 24) my app is not allowed to mute phone (set ringer mode to silent)在 Android 7(API 级别 24)中,我的应用不允许将手机静音(将铃声模式设置为静音)
【发布时间】:2017-01-02 06:00:18
【问题描述】:

我有一个应用程序,它通过使用 AudioManager 并使用以下代码将振铃模式设置为静音来使手机静音:

AudioManager audioManager = 
    (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
try {
    audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT)
} catch (Exception e) {
    e.printStackTrace();
}

这适用于 Android 6,但现在使用 Android 7,我收到以下错误:

System.err: java.lang.SecurityException: Not allowed to change Do Not Disturb state
System.err: at android.os.Parcel.readException(Parcel.java:1683)
System.err: at android.os.Parcel.readException(Parcel.java:1636)
System.err: at android.media.IAudioService$Stub$Proxy.setRingerModeExternal(IAudioService.java:962)
System.err: at android.media.AudioManager.setRingerMode(AudioManager.java:1022)
System.err: at controllers.SearchResultController.mutePhone(SearchResultController.java:185)

我需要申请什么新权限才能完成这项工作吗?

我查看了 Android 权限列表,但找不到任何相关的内容。

【问题讨论】:

    标签: android android-audiomanager android-7.0-nougat


    【解决方案1】:

    在 Android 设备中,您必须授予 DoNotDisturb 访问您的应用的权限

    【讨论】:

    • 请解释一下如何回答这个问题?
    【解决方案2】:

    嘿, 如果有人在 Kotlin 中需要此权限,您就在这里

    var notificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && !notificationManager.isNotificationPolicyAccessGranted
        ) {
            val intent = Intent(
                Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS
            )
            startActivity(intent)
        }
    

    非常感谢您的建议,这些建议可以挽救生命! :D

    【讨论】:

      【解决方案3】:

      我只在模拟器中遇到过这个问题。当我在我的手机上运行该应用程序时,它永远不会出现并且它按预期工作。

      【讨论】:

        【解决方案4】:

        感谢您的回答,这里有一些更详细的信息。

        为了能够将振铃模式设置为静音,您必须请求访问通知策略的权限(就像@ucsunil 所说的那样)。

        <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
        

        然后,检查您是否有此权限。如果您不这样做,请为您的应用打开“请勿打扰”设置:

        NotificationManager notificationManager = 
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && !notificationManager.isNotificationPolicyAccessGranted()) {
        
            Intent intent = new Intent(
                                android.provider.Settings
                                .ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
        
            startActivity(intent);
        }
        

        当您运行 startActivity() 时,Android 会为您的应用打开“请勿打扰”访问设置。

        让我感到困惑的是,请求此权限的方式与其他权限完全不同。

        仅供参考,这里是请求权限的方式READ_CONTACTS:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.READ_CONTACTS)
                == PackageManager.PERMISSION_DENIED) {
        
            ActivityCompat.requestPermissions(activity,
                new String[]{ Manifest.permission.READ_CONTACTS },
                    REQUEST_CODE_READ_CONTACTS);
        }
        

        【讨论】:

        • 请勿打扰访问来自 SDK 23 Marshmallow。所以&gt;= Build.VERSION_CODES.M BTW 对&lt;uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /&gt; 来说是必要的
        • 令人惊讶的是,在 Android 中,简单的事情往往变得如此复杂。这是解决方案..
        • @RicardoPessoa:在使用 Android M (23) 的虚拟手机上运行我的应用程序时,我不需要请求“请勿打扰”权限即可静音振铃,仅在 Android N ( 24).
        • @RicardoPessoa:对不起,我的错误。当您使用 audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); 使手机静音时,您在 Android M 中不需要此权限,但是当您使用 notificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 使手机静音时,它适用于 Android M 和之后,您需要请求此权限。更新了我上面的答案。
        • 在我的情况下,我的手机从不为此烦恼,但在某些时候它开始抛出该异常。这很奇怪,但我很高兴知道其他人已经找到了这个解决方案
        【解决方案5】:

        我已经通过打开设置菜单并在 api > 23 时要求用户授予权限来解决此问题。

        只需从任何地方调用 requestMutePermissions() 即可!

        private void requestMutePermissions() {
            try {
                if (Build.VERSION.SDK_INT < 23) {
                    AudioManager audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
                    audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                } else if( Build.VERSION.SDK_INT >= 23 ) {
                    this.requestForDoNotDisturbPermissionOrSetDoNotDisturbForApi23AndUp();
                }
            } catch ( SecurityException e ) {
        
            }
        }
        
        private void requestForDoNotDisturbPermissionOrSetDoNotDisturbForApi23AndUp() {
        
            NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
            // if user granted access else ask for permission
            if ( notificationManager.isNotificationPolicyAccessGranted()) {
                AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
                audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
            } else{
                // Open Setting screen to ask for permisssion
                Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
                startActivityForResult( intent, ON_DO_NOT_DISTURB_CALLBACK_CODE );
            }
        }
        
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            // Check which request we're responding to
            if (requestCode == ON_DO_NOT_DISTURB_CALLBACK_CODE ) {
                this.requestForDoNotDisturbPermissionOrSetDoNotDisturbForApi23AndUp();
            }
        }
        

        【讨论】:

        • 有没有办法将用户直接带到您应用的活动,而不是所有应用的活动?我想减少我们的用户为了启用权限而必须执行的步骤。
        • @TALE 我确实看到了一个应用程序,它会闪烁并突出显示该窗口中需要切换的特定行,用于请求权限的应用程序,所以至少看起来有可能。
        【解决方案6】:

        ACCESS_NOTIFICATION_POLICY 被视为“正常”权限,这意味着您不必在运行时请求权限。您只需将权限添加到 AndroidManifest.xml

            <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
        

        然后,要将所有通知静音,您可以将中断过滤器设置为 INTERRUPTION_FILTER_NONE

        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter();
                    notificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
                }
        

        INTERRUPTION_FILTER_ALARMS - 仅限警报
        INTERRUPTION_FILTER_ALL - 普通过滤器
        INTERRUPTION_FILTER_NONE - 无中断 (MUTE)
        INTERRUPTION_FILTER_PRIORITY - 优先中断

        我用

         int previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter();
        

        稍后在 onPause() 或 onStop() 时重置过滤器

        【讨论】:

        • 谢谢,有机会我会试试的。我想当我收到提到的错误时,我已经在 AndroidManifest.xml 中有 ACCESS_NOTIFICATION_POLICY,但我注意到我使用了不同的方法来关闭通知(audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT)),这可能已经过时了。我会尝试改用 notificationManager 看看效果是否更好。
        • 我终于开始为 Android M 及更高版本实现 notificationManager.setInterruptionFilter()。谢谢!正因为如此,我不得不开始检查 isNotificationPolicyAccessGranted() 也适用于 Android M(不仅仅是 N,我在原始答案中说过)。
        【解决方案7】:

        您正在寻找的访问权限是:

        <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
        

        您需要请求用户向您提供此特定权限。

        【讨论】:

          【解决方案8】:

          根据 Android 文档,您必须授予对“请勿打扰”的访问权限。

          从 N 起,除非应用已被授予“请勿打扰”访问权限,否则不允许进行会切换“请勿打扰”的铃声模式调整。请参阅 isNotificationPolicyAccessGranted()。

          请查看link

          希望对你有帮助!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-11-15
            • 1970-01-01
            • 2011-02-07
            • 2013-05-15
            • 1970-01-01
            • 2011-06-21
            • 1970-01-01
            相关资源
            最近更新 更多