简体   繁体   English

在 Android 7(API 级别 24)中,我的应用程序不允许将电话静音(将铃声模式设置为静音)

[英]In Android 7 (API level 24) my app is not allowed to mute phone (set ringer mode to silent)

I have an app that mutes the phone by using AudioManager and setting ringer mode to silent with this code:我有一个应用程序,它使用 AudioManager 将电话静音,并使用以下代码将铃声模式设置为静音:

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

This works with Android 6, but now with Android 7, I get the following error:这适用于 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)

Are there any new permissions I need to ask for to make this work?是否需要任何新权限才能使这项工作正常进行?

I looked through the Android permissions list, but couldn't find any that seemed relevant.我查看了 Android 权限列表,但找不到任何似乎相关的内容。

Thanks for your answers, here is a little more detail.感谢您的回答,这里有更多细节。

To be able to set ringer mode to silent, you must ask permission to access notification policy (like @ucsunil said).为了能够将铃声模式设置为静音,您必须请求访问通知策略的权限(如@ucsunil 所说)。

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

Then, check if you have this permission.然后,检查您是否拥有此权限。 If you do not, open the settings for "Do Not Disturb access" for your app:如果不这样做,请为您的应用打开“请勿打扰访问”设置:

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

When you run startActivity(), Android opens the Do Not Disturb access settings for your app.当您运行 startActivity() 时,Android 会为您的应用打开“请勿打扰”访问设置。

What confused me, was that the way to ask for this permission is completely different from other permissions.让我困惑的是,请求此权限的方式与其他权限完全不同。

Just for reference, here is the way to ask for permission READ_CONTACTS:仅供参考,这里是请求权限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);
}

The access you are looking for is:您正在寻找的访问是:

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

You need to request the user to provide you with this specific permission.您需要请求用户向您提供此特定权限。

ACCESS_NOTIFICATION_POLICY is considered a "normal" permission which means you do NOT have to request permission at runtime. ACCESS_NOTIFICATION_POLICY 被视为“正常”权限,这意味着您不必在运行时请求权限。 You only have to add the permission to AndroidManifest.xml您只需要将权限添加到 AndroidManifest.xml

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

Then, to mute all notifications you can set the Interruption filter to INTERRUPTION_FILTER_NONE然后,要将所有通知静音,您可以将中断过滤器设置为 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 - Alarms only INTERRUPTION_FILTER_ALARMS - 仅警报
INTERRUPTION_FILTER_ALL - Normal filter INTERRUPTION_FILTER_ALL - 普通过滤器
INTERRUPTION_FILTER_NONE - No interruptions (MUTE) INTERRUPTION_FILTER_NONE - 无中断(静音)
INTERRUPTION_FILTER_PRIORITY - Priority interruptions INTERRUPTION_FILTER_PRIORITY - 优先中断

I use我用

 int previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter();

to reset the filter later when onPause() or onStop()稍后在 onPause() 或 onStop() 时重置过滤器

I've resolved this issue by opening Setting menu and asking user to grant permission for it if api > 23.我已经通过打开设置菜单并要求用户在 api > 23 时为其授予权限解决了这个问题。

Just call requestMutePermissions() from anywhere and it will work!只需从任何地方调用 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();
    }
}

Based on Android documentation, you have to grant access to Do Not Disturb.根据 Android 文档,您必须授予对“请勿打扰”的访问权限。

From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed unless the app has been granted Do Not Disturb Access.从 N 开始,除非应用程序已被授予“请勿打扰”访问权限,否则将不允许切换“请勿打扰”的铃声模式调整。 See isNotificationPolicyAccessGranted().请参阅 isNotificationPolicyAccessGranted()。

Please check the link请检查链接

Hope it helps!希望有帮助!

Hy, If anyone needs this permission in Kotlin, here you are嘿,如果有人在 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)
    }

I really appreciate your advices that was life saving!我真的很感谢你挽救生命的建议! :D :D

I faced this issue only in an Emulator.我只在模拟器中遇到过这个问题。 When i run the app on my mobile it never comes and it works as expected.当我在我的手机上运行该应用程序时,它永远不会出现并且按预期工作。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android:铃声模式改为静音不会阻止手机振动 - Android: Ringer mode changed to silent doesn't stop the phone vibrating 如何将铃声模式完全设置为静音? - How to completely set ringer mode to silent? 检查android模拟器是否处于无声铃声模式 - Checking android emulator is in Silent Ringer Mode or not 在静音模式下在Android应用中手动将声音静音吗? - Manually mute sound in Android app when in silent mode? Android 8:当铃声模式为静音时,无法将铃声模式更改为非静音 - Android 8: Can't change ringer mode to non-silent when ringer mode is silent 将我的手机设置为静音模式 - Set my mobile phone to silent mode 加速度计,用于检测要将手机的铃声模式更改为Ringer_Mode_silent的设备的运动 - the accelerometer which detect the movement of the device that want to change the ringer mode of the phone to Ringer_Mode_silent 铃声模式在 Android 中静音 工作室在 Android 中不工作 11 - Ringer Mode Silent in Android Studio not working in Android 11 即使铃声处于静音模式,也可以在我的应用程序中播放声音 - Play sounds in my application even though ringer is in silent mode 在Android 8中将铃声模式正常更改为静音时的怪异行为 - Weird behavior when changing ringer mode normal to silent in android 8
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM