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

Android Automotive媒体播放器创建失败,setDataSource报错求助

Android Auto 网络音频播放失败问题排查与正确实现

问题描述

尝试在Android Auto中实现简单的网络音频流式播放器,但调用播放函数时,MediaPlayer无法通过URL设置数据源,抛出以下错误:

E/MediaPlayerNative: Unable to create media player
java.io.IOException: setDataSource failed.: status=0x80000000

错误栈

E/MediaPlayerNative: Unable to create media player W/System.err: java.io.IOException: setDataSource failed.: status=0x80000000
W/System.err:     at android.media.MediaPlayer.nativeSetDataSource(Native Method)
W/System.err:     at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1173)
W/System.err:     at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1160)
W/System.err:     at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1125)
W/System.err:     at com.auslanka.app.common.HelloWorldService.player(HelloWorldService.kt:42)
W/System.err:     at com.auslanka.app.common.HelloWorldService.onCreateSession(HelloWorldService.kt:14)
W/System.err:     at androidx.car.app.CarAppService.onCreateSession(CarAppService.java:283)
W/System.err:     at androidx.car.app.CarAppBinder.lambda$onAppCreate$0$androidx-car-app-CarAppBinder(CarAppBinder.java:115)
W/System.err:     at androidx.car.app.CarAppBinder$$ExternalSyntheticLambda6.dispatch(Unknown Source:8)
W/System.err:     at androidx.car.app.utils.RemoteUtils.lambda$dispatchCallFromHost$0(RemoteUtils.java:149)
W/System.err:     at androidx.car.app.utils.RemoteUtils$$ExternalSyntheticLambda2.run(Unknown Source:6)
W/System.err:     at android.os.Handler.handleCallback(Handler.java:883)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:100)
W/System.err:     at android.os.Looper.loop(Looper.java:214)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7356)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

原始代码

class HelloWorldScreen(carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
    val mGridIcon = IconCompat.createWithResource(
        carContext, R.drawable.mainscreenlogo
    )

    val gridItemCar = GridItem.Builder()
        .setTitle("Car Info")
        .setImage(
            CarIcon.Builder(mGridIcon).build(),
            GridItem.IMAGE_TYPE_LARGE
        ).setOnClickListener(this::player).build()
    val gridList = ItemList.Builder()
        .addItem(gridItemCar).build()
   return GridTemplate.Builder()
        .setSingleList(gridList)
        .build()
}
private fun player(){
    var mediaPlayer = MediaPlayer()

    var audioUrl = "https://url"

    var customUri: Uri = Uri.parse(audioUrl)


    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC)
    mediaPlayer.setAudioAttributes(
        AudioAttributes. Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .build()
    )
    if(!mediaPlayer.isPlaying){
        try {

            mediaPlayer.setDataSource(audioUrl)
            mediaPlayer.prepareAsync()
            mediaPlayer.setOnPreparedListener {
                mediaPlayer.start()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        Log.d("Player" , "Audio started playing..") }
    else {
        if (mediaPlayer.isPlaying) {
            mediaPlayer.stop()
            mediaPlayer.reset()
            //  mediaPlayer.release()
            Log.d("Player" , "Player Released")
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC)


        } else {
            Log.d("Player" , "Audio not played.. Check Error")
        }
    }
}}

问题原因分析

  1. 未遵循Android Auto音频规范:直接使用系统MediaPlayer不符合车载音频架构要求,需通过CarAudioManager管理音频焦点,适配车载系统的音频策略。
  2. 资源管理混乱:每次点击创建新MediaPlayer实例,未正确释放旧实例,导致资源泄漏。
  3. 权限与网络配置缺失:未声明网络权限,或音频URL不可访问(如HTTP协议被Android 9+限制、证书无效)。
  4. 音频属性配置冲突:同时调用setAudioStreamType(旧API)和setAudioAttributes(推荐API),引发配置冲突。

正确实现方案

1. 声明必要权限

在AndroidManifest.xml中添加:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 若使用HTTP音频,需添加以下配置 -->
<application android:usesCleartextTraffic="true">

2. 完整代码示例

import android.media.AudioAttributes
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.util.Log
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.GridItem
import androidx.car.app.model.GridTemplate
import androidx.car.app.model.IconCompat
import androidx.car.app.model.ItemList
import java.io.IOException

class AudioPlayerScreen(carContext: CarContext) : Screen(carContext) {
    private val TAG = "AudioPlayerScreen"
    private var mediaPlayer: MediaPlayer? = null
    private var audioManager: AudioManager? = null
    private var audioFocusRequest: AudioFocusRequest? = null

    override fun onGetTemplate(): GridTemplate {
        val mGridIcon = IconCompat.createWithResource(carContext, R.drawable.mainscreenlogo)

        val playItem = GridItem.Builder()
            .setTitle("播放网络音频")
            .setImage(
                androidx.car.app.model.CarIcon.Builder(mGridIcon).build(),
                GridItem.IMAGE_TYPE_LARGE
            )
            .setOnClickListener { togglePlayback() }
            .build()

        val gridList = ItemList.Builder()
            .addItem(playItem)
            .build()

        return GridTemplate.Builder()
            .setSingleList(gridList)
            .build()
    }

    override fun onStart() {
        super.onStart()
        audioManager = carContext.getSystemService(AudioManager::class.java)
        initAudioFocusRequest()
    }

    override fun onStop() {
        super.onStop()
        releaseMediaPlayer()
        abandonAudioFocus()
    }

    private fun initAudioFocusRequest() {
        val audioAttributes = AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .build()

        audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
            .setAudioAttributes(audioAttributes)
            .setOnAudioFocusChangeListener { focusChange ->
                when (focusChange) {
                    AudioManager.AUDIOFOCUS_LOSS -> stopPlayback()
                    AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> mediaPlayer?.pause()
                    AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> mediaPlayer?.setVolume(0.3f, 0.3f)
                    AudioManager.AUDIOFOCUS_GAIN -> {
                        mediaPlayer?.setVolume(1.0f, 1.0f)
                        if (!mediaPlayer?.isPlaying!!) mediaPlayer?.start()
                    }
                }
            }
            .build()
    }

    private fun requestAudioFocus(): Boolean {
        return audioManager?.requestAudioFocus(audioFocusRequest) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
    }

    private fun abandonAudioFocus() {
        audioManager?.abandonAudioFocusRequest(audioFocusRequest!!)
    }

    private fun togglePlayback() {
        if (mediaPlayer?.isPlaying == true) stopPlayback() else startPlayback()
    }

    private fun startPlayback() {
        if (!requestAudioFocus()) {
            Log.e(TAG, "获取音频焦点失败")
            return
        }

        if (mediaPlayer == null) {
            mediaPlayer = MediaPlayer().apply {
                setAudioAttributes(
                    AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                        .build()
                )
                setOnPreparedListener { it.start(); Log.d(TAG, "音频开始播放") }
                setOnErrorListener { _, what, extra ->
                    Log.e(TAG, "播放错误: what=$what, extra=$extra")
                    releaseMediaPlayer()
                    abandonAudioFocus()
                    true
                }
                setOnCompletionListener {
                    Log.d(TAG, "播放完成")
                    releaseMediaPlayer()
                    abandonAudioFocus()
                }
            }
        }

        try {
            val audioUrl = "https://your-valid-audio-url.mp3" // 替换为有效音频URL
            mediaPlayer?.setDataSource(carContext, Uri.parse(audioUrl))
            mediaPlayer?.prepareAsync()
        } catch (e: IOException) {
            Log.e(TAG, "设置数据源失败", e)
            releaseMediaPlayer()
            abandonAudioFocus()
        }
    }

    private fun stopPlayback() {
        mediaPlayer?.stop()
        mediaPlayer?.reset()
        abandonAudioFocus()
        Log.d(TAG, "播放停止")
    }

    private fun releaseMediaPlayer() {
        mediaPlayer?.release()
        mediaPlayer = null
        Log.d(TAG, "MediaPlayer已释放")
    }
}

关键注意事项

  • 音频URL有效性:确保URL指向支持流式播放的音频文件(如MP3、AAC),且可被车载网络访问。
  • 生命周期绑定:在Screen的onStart/onStop中初始化和释放资源,避免内存泄漏。
  • 音频焦点处理:必须响应车载系统的音频焦点变化,适配导航、电话等优先级更高的音频场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:10:51