You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:01:14