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") } } }}
问题原因分析
- 未遵循Android Auto音频规范:直接使用系统
MediaPlayer不符合车载音频架构要求,需通过CarAudioManager管理音频焦点,适配车载系统的音频策略。 - 资源管理混乱:每次点击创建新
MediaPlayer实例,未正确释放旧实例,导致资源泄漏。 - 权限与网络配置缺失:未声明网络权限,或音频URL不可访问(如HTTP协议被Android 9+限制、证书无效)。
- 音频属性配置冲突:同时调用
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
相关产品推荐
相关产品推荐

