Android Media Player报错“Unable to create media player”:VideoView复用问题求助
解决Android VideoView/MediaPlayer复用导致的播放失败问题
看起来你遇到的是典型的VideoView内部MediaPlayer资源未正确释放导致的播放异常问题。第一次播放视频后,MediaPlayer处于占用状态,当你从字幕Activity返回或跳转到最后一个Activity时,旧的MediaPlayer资源没有被清理,导致新的播放请求无法创建或初始化媒体播放器。
我帮你梳理几个关键修复点,直接对应你的代码问题:
核心修复步骤
- 在重新设置视频源前,强制重置/释放VideoView的MediaPlayer:避免旧的播放器资源占用导致冲突
- 优化onActivityResult中的逻辑:移除不必要的重复Handler延迟,确保视频初始化代码执行顺序正确
- 统一管理VideoView的状态:在Activity生命周期的关键节点(比如onPause、onResume)也做相应的状态保存和恢复
修改后的主Activity代码
public class TelaHome extends Activity { VideoView video; int num = 0; ImageView videocheck; ImageView legcheck; Button butvideo; Button butleg; Button butstart; TextView textovideo; String nomedovideo; String urivideo; Uri Uridovideo; int cont = 0; int stop = 0; Boolean simvid = false; Boolean simleg = false; Intent videointent; Intent letraintent; Bundle pacotemain; Bundle letra; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tela_home); butstart = findViewById(R.id.butstart); butvideo = findViewById(R.id.butvideo); butleg = findViewById(R.id.butleg); videocheck = findViewById(R.id.imgvideocheck); legcheck = findViewById(R.id.imglegcheck); textovideo = findViewById(R.id.textovideo); video = findViewById(R.id.videoView); textovideo.setMovementMethod(new ScrollingMovementMethod()); butstart.setVisibility(View.INVISIBLE); videocheck.setImageResource(R.mipmap.ic_not_checked); textovideo.setText(""); MediaController mc = new MediaController(this); mc.setAnchorView(video); video.setMediaController(mc); butvideo.setOnClickListener(view -> launchMainActivity()); } // 新增:在Activity暂停时释放VideoView资源 @Override protected void onPause() { super.onPause(); if (video != null && video.isPlaying()) { video.pause(); } } // 新增:在Activity销毁时彻底释放MediaPlayer @Override protected void onDestroy() { super.onDestroy(); if (video != null) { video.stopPlayback(); // 这会内部释放MediaPlayer资源 } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 不要忘记调用父类方法! if (requestCode == 1) { if(resultCode == Activity.RESULT_OK){ videointent = data; pacotemain = videointent.getExtras(); if (pacotemain != null) { nomedovideo = pacotemain.getString("arquivo"); urivideo = pacotemain.getString("curPF"); if (urivideo != null) { // 关键修复:先停止当前播放并重置VideoView if (video.isPlaying()) { video.stopPlayback(); } // 重新设置视频源 Uridovideo = Uri.parse(urivideo); video.setVideoURI(Uridovideo); video.setOnPreparedListener(mediaPlayer -> video.start()); } if (nomedovideo != null) { // 简化格式获取逻辑,避免数组操作的潜在问题 String formato = nomedovideo.substring(nomedovideo.length() - 3); textovideo.setText(nomedovideo); } } new Handler(Looper.getMainLooper()).postDelayed(() -> { if (video.isPlaying()) { cont++; videocheck.setImageResource(R.mipmap.ic_checked); simvid = true; } }, 1000); } } if (requestCode == 7) { if(resultCode == Activity.RESULT_OK){ letraintent = data; letra = letraintent.getExtras(); if (letra != null){ legcheck.setImageResource(R.mipmap.ic_checked); simleg = true; } } } new Handler(Looper.getMainLooper()).postDelayed(() -> abrirplay(simvid, simleg, pacotemain, letra), 1500); } // 补充launchMainActivity方法(你的代码里没贴,这里假设是打开图库的逻辑) private void launchMainActivity() { // 这里写打开图库选择视频的Intent逻辑 } private void abrirplay(Boolean simvid, Boolean simleg, Bundle pacotemain, Bundle letra) { // 你的跳转逻辑 } }
关键修改说明
- 添加生命周期方法管理:在
onPause中暂停播放,onDestroy中调用stopPlayback()彻底释放MediaPlayer资源,这是避免资源泄漏的核心。 - 重置VideoView再设置新视频:在requestCode=1的分支里,每次设置新的视频URI前,先停止当前播放并释放旧的MediaPlayer,避免资源冲突。
- 修复Handler的使用:使用
Looper.getMainLooper()确保Handler在主线程运行,避免潜在的线程问题。 - 简化格式获取逻辑:用
substring替代数组操作,减少代码复杂度和潜在错误。 - 调用父类的onActivityResult:你之前的代码漏掉了
super.onActivityResult(...),这可能导致ActivityResult的逻辑异常。
另外,关于最后一个Activity的VideoView问题,同样要遵循这个原则:每次设置视频前,先调用stopPlayback()释放旧的MediaPlayer资源,再设置新的URI,这样就能避免"Unable to create media player"的错误。
内容的提问来源于stack exchange,提问作者Reinaldo Neto
相关产品推荐
相关产品推荐

