Xamarin.Forms中Android10-13下AudioManager无法切换扬声器的问题求助
解决Android 13下Xamarin.Forms通话时扬声器定时切换失效问题
1. 添加必要权限
在AndroidManifest.xml中补充以下权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
2. 改造服务为前台服务
Android 13对后台服务限制大幅收紧,必须以前台服务形式运行才能持续执行任务,同时优化音频管理器的使用逻辑:
[Service(ForegroundServiceType = ForegroundServiceType.MediaPlayback)] public class PhoneCallService : Service { private const int NotificationId = 1001; private AudioManager _audioManager; private CancellationTokenSource _taskCts; public override void OnCreate() { base.OnCreate(); _audioManager = (AudioManager)GetSystemService(Context.AudioService); _taskCts = new CancellationTokenSource(); } public override IBinder OnBind(Intent intent) { return null; } public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { // 创建前台通知通道(Android 8.0+要求) var channelId = "CallSpeakerControlChannel"; if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel(channelId, "通话扬声器控制", NotificationImportance.Low) { Description = "定时切换通话扬声器开关状态" }; var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.CreateNotificationChannel(channel); } // 构建前台通知 var notification = new NotificationCompat.Builder(this, channelId) .SetContentTitle("通话扬声器控制") .SetContentText("正在定时切换扬声器状态") .SetSmallIcon(Resource.Drawable.ic_notify_default) // 替换为你的项目通知图标 .SetPriority(NotificationCompat.PriorityLow) .Build(); // 启动前台服务 StartForeground(NotificationId, notification); // 启动定时切换任务 Task.Run(async () => { while (!_taskCts.Token.IsCancellationRequested) { // 仅在通话状态下执行切换 if (_audioManager.Mode == Mode.InCall) { _audioManager.SpeakerphoneOn = !_audioManager.SpeakerphoneOn; } await Task.Delay(TimeSpan.FromSeconds(30), _taskCts.Token); } }, _taskCts.Token); return StartCommandResult.Sticky; } public override void OnDestroy() { _taskCts.Cancel(); base.OnDestroy(); } }
3. 动态申请通知权限
Android 13及以上需要动态申请通知权限,在启动服务前执行:
if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu) { if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.PostNotifications) != Permission.Granted) { ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.PostNotifications }, 100); } }
关键修改说明
- 移除对
MainActivity静态AudioManager的依赖,在服务内部获取实例,避免上下文失效和内存泄漏 - 新增前台服务逻辑,满足Android 13后台任务运行要求
- 增加通话状态判断,确保仅在通话过程中切换扬声器
- 使用
CancellationTokenSource管理后台任务,服务销毁时及时终止任务,避免资源浪费
内容的提问来源于stack exchange,提问作者MomMan
相关产品推荐
相关产品推荐

