Service播放音乐报错:mediaPlayer.setDataSource触发IllegalStateException
问题分析与修复方案
错误根源
- 变量赋值顺序错误:先执行
Toast展示未初始化的str(此时为null),之后才从Intent中获取uri赋值给str,导致setDataSource传入无效参数 - MediaPlayer状态管理缺失:未重置MediaPlayer状态就重复设置数据源,当多次启动Service时,MediaPlayer处于非空闲状态,触发
IllegalStateException - 缺少准备流程:设置数据源后未调用
prepareAsync()/prepare(),MediaPlayer无法进入可播放状态
修复后的Service代码
public class MyService extends android.app.Service { private MediaPlayer mediaPlayer; private String str; private final IBinder binder = new LocalBinder(); @Override public void onCreate() { super.onCreate(); // onCreate中初始化MediaPlayer,避免重复实例化 mediaPlayer = new MediaPlayer(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 优先获取Intent中的uri参数 str = intent.getStringExtra("uri"); if (str == null || str.isEmpty()) { Toast.makeText(this, "无效音频地址", Toast.LENGTH_SHORT).show(); return START_STICKY; } Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); try { // 重置MediaPlayer到空闲状态,避免重复设置数据源异常 mediaPlayer.reset(); mediaPlayer.setDataSource(str); // 设置准备完成监听器 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { startmusic(); } }); // 异步准备(网络资源推荐用这个,本地资源可改用prepare()) mediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "音频加载失败", Toast.LENGTH_SHORT).show(); } return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); // 销毁时释放MediaPlayer资源,防止内存泄漏 if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } } public class LocalBinder extends Binder { MyService getService() { return MyService.this; } } @Override public IBinder onBind(Intent intent) { return binder; } public void startmusic() { if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } public void stopmusic() { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } } public boolean isplaying() { return mediaPlayer != null && mediaPlayer.isPlaying(); } }
启动Service代码优化
Intent intent = new Intent(getActivity(), MyService.class); // 确保uri非空再传递 if (ur != null && !ur.isEmpty()) { intent.putExtra("uri", ur); getActivity().startService(intent); } else { Toast.makeText(getActivity(), "音频地址为空", Toast.LENGTH_SHORT).show(); } // 注:当前代码仅创建了ServiceConnection但未调用bindService,若不需要绑定可删除该部分代码;若需绑定,需调用: // getActivity().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
额外注意事项
- 播放网络音频需在
AndroidManifest.xml添加权限:<uses-permission android:name="android.permission.INTERNET" /> - Android 10+播放本地文件需申请存储权限或通过MediaStore获取合法URI
- 建议通过绑定Service调用内部方法控制播放,减少重复启动Service导致的状态异常
内容的提问来源于stack exchange,提问作者mm m
相关产品推荐
相关产品推荐

