当前位置: 首页 > 知识库问答 >
问题:

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

薛淳
2023-03-14

在我的应用程序中,我已经授予了phone_state的权限,并且它正在顺利地检测接收/offhook/idle统计信息。

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()
        }
    }
}
<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 140 6-2091/?W/Audio_HW_Generic:没有向哈尔提供足够的数据,预期位置为1097356,只写了1097280 04-26 04:55:04.434 506 5-5065/?d/AndroidRuntime:关闭VM 04-26 04:55:04.446 506 5-5065/?E/AndroidRuntime:致命异常:main process:com.example.hasan.ringer,PID:5065 java.lang.securityException(parcel.java:1942)在Android.os.parcel.readException(parcel.java:1865)在Android.media.iAudioService$stub$proxy.setringerModeExterner(IAudioService.java:1161)在Android.media.audioManager.setringerMode(AudioService.java:1099)在20)在Android.view.view.performClick(view.java:6579)在Android.view.view.performClickInternal(view.java:6556)在Android.view.view.access$3100(View.java:777)在Android.view.view.view$performClick.run(view.java:25660)在Android.os.handler.handleCallback(handler.java:819)在Android.os.handler.dispatchMessage(handler.java:99)在reflect.Method.invoke(本机方法)位于com.android.internal.os.runtimeInit$methodandargscaller.run(runtimeinit.java:438)在com.android.internal.os.zygoteinit.main(zygoteinit.java:823)由:android.os.remoteException:远程堆栈跟踪:at com.android.server.audio.audioService.setringerModeExternal(AudioService.java:2333)在android.media.iAudioService$stub.onTransact(IaudioService.java:199)ActivityManager:强制完成活动com.example.hasan.ringer/.MainActivity

共有1个答案

秋向阳
2023-03-14

我发现答案是,access_notification_policy权限是必需的,在清单下面的required行中:

<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)
}
 类似资料:
  • 我有一个问题,正确的对话片段删除后,方向被改变。我想这是由于旧的上下文,因为在该活动被重新创建后,会创建一个新的活动和相应的上下文。我知道我可以在onSaveInstance中设置一些变量来保存对话框状态,如果必要的话重新创建对话框,或者只在清单“定向”中放置一个属性。但是,也许有更好的方法来做到这一点,不在manifest中硬编码,也不在onSaveIntance中手动保存?我还尝试在main片

  • 我在一个片段中遇到了一个问题,该片段从新的Google Maps API中嵌入了SuportMapFragment。当创建我的片段时,它从方法开始,在中获取一些数据。当这种情况发生时,MapFragment保持在屏幕外,而是显示进度条。 完成后,我向MapView的事件注册。然后我显示片段,这导致地图视图被显示和布局。被触发,动画开始。 多谢!

  • 问题内容: 当我退出“活动”退出(通过“后退”按钮)时,我的应用程序崩溃。据我所知,这是在Android代码库中发生的,而不是我的,但是我并不完全相信。 这是来自adb的stacktrace: 有人有什么想法/建议吗? 问题答案: 无助,因为没有代码。还在看 造成原因:android.app.Activity.performStop(Activity.java:3575)上的java.lang.N

  • 我第一次试着用docker。我需要它使selenium在服务器上运行。所以我可以把这个脚本放到任何一台服务器上,这样就可以毫不费力地工作了。但是突然间它就不起作用了,它就不起作用了。我试着在谷歌上搜索,但什么都没有。现在我在这里寻求帮助。也许我错过了什么,也许我把事情搞砸了,现在我看到了解决办法。解决方案是下载chromedriver,拒绝独立运行selenium。 开始硒 Dockerfile去

  • 我使用的是IntelliJIDEA CE edition(11.0.4)的最新版本。有一件事我在任何地方都找不到,它阻碍了我对Java/Spring的进一步改进。 控制器: 类:导入com.example.demo.interfaces.ISave; 类接口: 没什么特别的,只是为了掌握Spring和Java。 在我的控制器里,当我试图使用 我收到一个阻止应用启动的错误。以下是错误: 任务应用程序

  • 虽然以下两个框的边界半径量相同,但显示的结果不同。这是什么原因?我们怎样才能使它在每个盒子里看起来都一样呢。我们必须根据盒子的大小做数学运算吗?(我说的是为什么方框2不那么圆。) 我知道这是一种视错觉,但考虑到盒子的大小,我希望它看起来是一样的。 当我用百分比做的时候,边界半径会参差不齐。