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

Android 13系统下如何开启外拨电话的扬声器?

Xamarin.Forms 实现Android扬声器控制的适配方案

针对新Android版本中旧AudioManager方法失效的问题,这里提供一套完整的适配方案,核心是通过DependencyService调用原生API并处理版本权限差异:

1. 定义跨平台音频服务接口

在共享项目中创建统一接口,方便跨平台调用:

public interface IAudioService
{
    bool TurnOnSpeaker();
    bool TurnOffSpeaker();
    bool IsSpeakerActive();
}

2. Android端原生实现

配置Manifest权限

先在Android项目的AndroidManifest.xml中添加必要权限:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- 涉及音频录制/通话场景时需要,Android 6.0+需动态申请 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />

实现服务类

[assembly: Dependency(typeof(AndroidAudioService))]
namespace YourApp.Droid
{
    public class AndroidAudioService : IAudioService
    {
        public bool TurnOnSpeaker()
        {
            try
            {
                var audioManager = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
                
                // Android 10+ 必须通过AudioFocusRequest申请音频焦点
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
                {
                    var focusRequest = new AudioFocusRequest.Builder(AudioFocus.GainTransient)
                        .SetAudioAttributes(new AudioAttributes.Builder()
                            .SetUsage(AudioUsageKind.VoiceCommunication)
                            .SetContentType(AudioContentType.Speech)
                            .Build())
                        .Build();
                    
                    if (audioManager.RequestAudioFocus(focusRequest) != AudioFocusRequestResult.Granted)
                    {
                        return false;
                    }
                }
                else
                {
                    // 旧版本直接请求音频焦点
                    if (audioManager.RequestAudioFocus(null, Stream.VoiceCall, AudioFocus.Gain) != AudioFocusRequestResult.Granted)
                    {
                        return false;
                    }
                }

                // 设置音频模式并开启扬声器
                audioManager.Mode = Mode.InCall;
                audioManager.SetSpeakerphoneOn(true);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"开启扬声器失败: {ex.Message}");
                return false;
            }
        }

        public bool TurnOffSpeaker()
        {
            try
            {
                var audioManager = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
                audioManager.SetSpeakerphoneOn(false);
                
                // 释放音频焦点
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
                {
                    var focusRequest = new AudioFocusRequest.Builder(AudioFocus.GainTransient)
                        .SetAudioAttributes(new AudioAttributes.Builder()
                            .SetUsage(AudioUsageKind.VoiceCommunication)
                            .SetContentType(AudioContentType.Speech)
                            .Build())
                        .Build();
                    audioManager.AbandonAudioFocusRequest(focusRequest);
                }
                else
                {
                    audioManager.AbandonAudioFocus(null);
                }
                
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"关闭扬声器失败: {ex.Message}");
                return false;
            }
        }

        public bool IsSpeakerActive()
        {
            var audioManager = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
            return audioManager.IsSpeakerphoneOn;
        }
    }
}

3. 动态申请权限(Android 6.0+)

RECORD_AUDIO属于危险权限,必须在运行时申请,可在页面初始化或按钮点击前处理:

private async Task CheckAndRequestPermissions()
{
    var micStatus = await Permissions.CheckStatusAsync<Permissions.Microphone>();
    if (micStatus != PermissionStatus.Granted)
    {
        var result = await Permissions.RequestAsync<Permissions.Microphone>();
        if (result != PermissionStatus.Granted)
        {
            await DisplayAlert("提示", "需要麦克风权限才能控制扬声器", "确定");
        }
    }
}

4. 在Xamarin.Forms页面调用

通过DependencyService获取服务实例并使用:

private async void EnableSpeakerBtn_Clicked(object sender, EventArgs e)
{
    await CheckAndRequestPermissions();
    var audioService = DependencyService.Get<IAudioService>();
    if (audioService != null)
    {
        var success = audioService.TurnOnSpeaker();
        await DisplayAlert("结果", success ? "扬声器已开启" : "开启失败", "确定");
    }
}

关键适配点

  • 音频焦点:Android 10(API 29)之后必须通过AudioFocusRequest申请焦点,否则SetSpeakerphoneOn会失效。
  • 音频模式:根据场景选择Mode.InCall(通话)或Mode.Normal(媒体),模式不对也可能导致扬声器无法开启。
  • 权限区分:MODIFY_AUDIO_SETTINGS是正常权限,只需Manifest声明;RECORD_AUDIO需要动态申请。

内容的提问来源于stack exchange,提问作者MomMan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:16:01