java - 为什么 AudioManager 在 RingerMode 改变时崩溃?

标签 java android kotlin

在我的应用程序中,我已经授予了 PHONE_STATE 的权限,它正在顺利检测接收/摘机/空闲状态。

如果来电来自重新指定的号码,即使手机静音,我也需要手机响铃,所以我正在更改 AudioManager 状态如下,但应用程序一旦崩溃试图改变铃声模式!!

class PhoneStateReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        val state = intent.getStringExtra(TelephonyManager.EXTRA_STATE)
        val incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)

        val audio = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
        if (incomingNumber == "(650) 555-1212" && state == TelephonyManager.EXTRA_STATE_RINGING) {
            Toast.makeText(context, "Ringing ${audio.ringerMode}", Toast.LENGTH_SHORT).show()
            if(audio.ringerMode == AudioManager.RINGER_MODE_SILENT)
            audio.apply {    // The app crash here!!
                ringerMode = AudioManager.RINGER_MODE_NORMAL
                setStreamVolume(AudioManager.STREAM_RING,
                        audio.getStreamMaxVolume(AudioManager.STREAM_RING),
                        AudioManager.FLAG_ALLOW_RINGER_MODES or AudioManager.FLAG_PLAY_SOUND)
            }
            val ring = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
            val r = RingtoneManager.getRingtone(context, ring)
            r.play()
        }
        if (state == TelephonyManager.EXTRA_STATE_OFFHOOK) {
             audio.ringerMode = AudioManager.RINGER_MODE_SILENT
            Toast.makeText(context, "On Call ", Toast.LENGTH_SHORT).show()
        }
        if (state == TelephonyManager.EXTRA_STATE_IDLE) {
            Toast.makeText(context, "IDLE", Toast.LENGTH_SHORT).show()
        }
    }
}

AndroidManifest.xml 中:

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

<receiver
    android:name=".broadcasts.PhoneStateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver> 

更新

这是 Logcat 错误:

04-26 04:55:04.422 1406-2091/? W/audio_hw_generic: Not supplying enough data to HAL, expected position 1097356 , only wrote 1097280 04-26 04:55:04.434 5065-5065/? D/AndroidRuntime: Shutting down VM 04-26 04:55:04.446 5065-5065/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.hasan.ringer, PID: 5065 java.lang.SecurityException: Not allowed to change Do Not Disturb state at android.os.Parcel.createException(Parcel.java:1942) at android.os.Parcel.readException(Parcel.java:1865) at android.media.IAudioService$Stub$Proxy.setRingerModeExternal(IAudioService.java:1161) at android.media.AudioManager.setRingerMode(AudioManager.java:1099) at com.example.hasan.ringer.MainActivity$onCreate$1.onClick(MainActivity.kt:20) at android.view.View.performClick(View.java:6579) at android.view.View.performClickInternal(View.java:6556) at android.view.View.access$3100(View.java:777) at android.view.View$PerformClick.run(View.java:25660) at android.os.Handler.handleCallback(Handler.java:819) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) Caused by: android.os.RemoteException: Remote stack trace: at com.android.server.audio.AudioService.setRingerModeExternal(AudioService.java:2333) at android.media.IAudioService$Stub.onTransact(IAudioService.java:199) at android.os.Binder.execTransact(Binder.java:726) 04-26 04:55:04.453 1680-4664/system_process W/ActivityManager: Force finishing activity com.example.hasan.ringer/.MainActivity

最佳答案

我找到了答案,需要 ACCESS_NOTIFICATION_POLICY 的许可, list 中需要以下行:

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

并且权限是从 ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS 授予的,如下所示:

val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !notificationManager.isNotificationPolicyAccessGranted) {

        val intent = Intent(
                android.provider.Settings
                        .ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)

        startActivity(intent)
}

关于java - 为什么 AudioManager 在 RingerMode 改变时崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50010586/

相关文章:

java - Spring data gemfire 不支持 REQUIRES_NEW 事务

android - Kotlin 中硬关键字和软关键字的区别

Android:蓝牙连接、套接字和线程

Android 应用程序加载屏幕

android - 将Android Studio更新到版本4.1之后原因:重复输入:META-INF/new_core_debug.kotlin_module发生此错误?如何解决

java - 如何从通过 MyBatis 映射器方法调用的 PostgreSQL 函数获取服务器消息(引发通知)?

java - 将数组传递给测试类构造函数

java - 如何使用java配置在spring中配置waffle

android - 在 Kotlin 中传递多个 lambda 函数以处理成功/失败的最佳方法

kotlin - 构造函数是 Kotlin 中的函数吗?