Android 13下InCallService拨号应用通话振铃时振动异常求助
Android 13中InCallService通话振铃阶段振动被抑制的解决方案
问题描述
我使用InCallService开发了一款带有自定义铃声和振动功能的简易拨号应用,该应用在Android 8上运行正常。但在Android 13系统中,非通话状态下振动功能正常,而在通话振铃阶段,振动被抑制(仅持续50-100ms,预期为1000ms),振动由前台Activity触发。推测可能遗漏了Android新版本的相关特性,现附上代码及配置:
振动触发代码
private final VibrationEffect vibrationEffect = createOneShot(1000, DEFAULT_AMPLITUDE); if (SDK_INT >= 33) vibrator.vibrate(vibrationEffect, VibrationAttributes.createForUsage(VibrationAttributes.USAGE_RINGTONE)); else vibrator.vibrate(vibrationEffect, new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
清单文件配置
<uses-permission android:name="android.permission.VIBRATE" /> <service android:name=".Serv" android:exported="true" android:permission="android.permission.BIND_INCALL_SERVICE"> <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING" android:value="true" /> <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" /> <intent-filter> <action android:name="android.telecom.InCallService" /> </intent-filter> </service>
问题分析与解决方案
Android 13(API 33)针对通话场景的振动行为新增了更严格的系统管控逻辑,当使用USAGE_RINGTONE这类通用振铃属性时,系统可能会优先接管振动行为,导致自定义振动被截断。以下是针对性的解决方法:
1. 更换振动属性为通信信号专用类型
将振动属性从USAGE_RINGTONE/USAGE_NOTIFICATION_RINGTONE替换为USAGE_COMMUNICATION_SIGNALLING,该属性专门用于通话振铃、来电提醒这类通信信号场景,系统对其的限制更少:
private final VibrationEffect vibrationEffect = VibrationEffect.createOneShot(1000, VibrationEffect.DEFAULT_AMPLITUDE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { vibrator.vibrate(vibrationEffect, VibrationAttributes.createForUsage(VibrationAttributes.USAGE_COMMUNICATION_SIGNALLING)); } else { vibrator.vibrate(vibrationEffect, new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_COMMUNICATION_SIGNALLING).build()); }
2. 确保前台Activity的优先级
在触发振动前,强制将Activity移至前台,避免系统因优先级问题中断振动:
if (!isFinishing() && !isDestroyed()) { moveTaskToFront(getTaskId(), 0); } // 执行振动逻辑
3. 规避系统默认振铃振动冲突
Android 13中系统会自动触发通话振铃振动,可能与自定义振动冲突。可以通过TelecomManager监听通话状态,在确认振铃状态后,再触发自定义振动:
TelecomManager telecomManager = getSystemService(TelecomManager.class); if (telecomManager != null && telecomManager.isRinging()) { // 执行自定义振动逻辑 }
4. 再次确认权限有效性
虽然非通话状态振动正常,但仍可在振动逻辑前增加权限检查,确保权限未被系统回收:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.VIBRATE) == PackageManager.PERMISSION_GRANTED) { // 执行振动逻辑 }
内容的提问来源于stack exchange,提问作者siapost
相关产品推荐
相关产品推荐

