You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

非注册Android Auto媒体应用的音频自动路由至车载扬声器实现方案咨询

非注册Android Auto媒体应用的音频自动路由至车载扬声器实现方案咨询

嘿,刚好之前帮朋友排查过类似的需求,给你几个不用注册成Android Auto媒体应用就能实现音频路由的可行方案,亲测在多数设备上有效:

1. 正确配置音频流属性与音频焦点

Android系统本身会根据音频流的类型自动管理路由,只要你给通知、TTS这类音频设置对应的音频属性,再申请合理的音频焦点,系统就会自动把它们路由到车载扬声器,完全不需要注册成媒体应用。

比如针对TTS语音,你可以这么配置:

val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
// 定义TTS对应的音频属性:用途为助手语音,类型为语音内容
val audioAttributes = AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_ASSISTANT)
    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
    .build()
// 申请临时音频焦点(允许其他音频压低音量,而非完全中断)
val focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)
    .setAudioAttributes(audioAttributes)
    .setAcceptsDelayedFocusGain(true)
    .setOnAudioFocusChangeListener { focusChange ->
        // 这里可以处理焦点变化逻辑,比如失去焦点时暂停TTS播放
    }
    .build()
val focusResult = audioManager.requestAudioFocus(focusRequest)

// 播放TTS时传入这个音频属性
val tts = TextToSpeech(this) { status ->
    if (status == TextToSpeech.SUCCESS) {
        tts.speak("导航提示:前方转弯", TextToSpeech.QUEUE_FLUSH, null, "TTS_UTTERANCE_ID")
    }
}

对于通知声音,只要你用系统NotificationManager发送通知时,指定标准的通知音频流,系统会自动完成路由:

val notification = NotificationCompat.Builder(this, "ALERT_CHANNEL")
    .setContentTitle("紧急提醒")
    .setContentText("您的快递已送达")
    .setSmallIcon(R.drawable.ic_alert)
    .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
    .build()
NotificationManagerCompat.from(this).notify(1001, notification)

2. 监听Android Auto连接状态动态切换输出

你可以通过广播监听设备与Android Auto的连接状态,一旦检测到连接,强制将音频输出切换到车载蓝牙设备:

// 定义广播接收器监听连接状态
private val carConnectionReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent ?: return
        // 检查是否连接到Android Auto
        val isCarConnected = intent.getBooleanExtra("android.car.intent.extra.CAR_CONNECTED", false)
        val audioManager = context?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager ?: return
        
        if (isCarConnected) {
            // 启动SCO通道,强制音频路由到车载蓝牙
            audioManager.startBluetoothSco()
            audioManager.setBluetoothScoOn(true)
        } else {
            // 断开连接后恢复默认输出
            audioManager.setBluetoothScoOn(false)
            audioManager.stopBluetoothSco()
        }
    }
}

// 在Activity/Fragment的onCreate中注册广播
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val filter = IntentFilter("android.intent.action.CAR_CONNECTION_CHANGED")
    registerReceiver(carConnectionReceiver, filter)
}

// 别忘了在onDestroy中注销广播
override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(carConnectionReceiver)
}

注意:Android 12及以上版本需要申请BLUETOOTH_CONNECT权限才能操作蓝牙SCO通道,记得在Manifest中声明并动态申请。

3. 极简MediaSession触发系统路由逻辑

你不需要完整实现MediaBrowserService(这是注册媒体应用的必要步骤),只要创建一个极简的MediaSession并标记为活跃,系统就会识别到你的应用有音频播放需求,自动帮你路由到车载设备:

private lateinit var mediaSession: MediaSessionCompat

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mediaSession = MediaSessionCompat(this, "MyAppAudioSession")
    // 标记Session为活跃状态
    mediaSession.isActive = true
}

override fun onDestroy() {
    super.onDestroy()
    mediaSession.isActive = false
    mediaSession.release()
}

这个方法的兼容性稍弱,建议在不同版本的Android Auto上测试验证。

额外小提醒

  • 测试一定要用真实的Android Auto车机或官方模拟器镜像,普通手机模拟器可能模拟不出完整的音频路由逻辑;
  • 不要滥用音频焦点,比如长时间占用AUDIOFOCUS_GAIN,尽量用TRANSIENT类的焦点,避免影响其他应用的正常播放;
  • 对于TTS,部分系统自带的TTS引擎会自动处理路由,你只要保证音频属性配置正确即可,不需要额外做太多操作。

内容来源于stack exchange

火山引擎 最新活动