我有一个主要目标是播放特定视频文件的应用程序。
它有时会正确播放视频。但有时候它给了我这个错误:
03-21 14:52:36.181: I/AwesomePlayer(119):
setDataSource_l('/data/data/my.package.name/files/MyMovie.mp4')
03-21 14:52:36.196: W/VideoView(26612): Unable to open content: /data/data/my.package.name/files/MyMovie.mp4
03-21 14:52:36.196: W/VideoView(26612): java.lang.IllegalArgumentException: The surface has been released
03-21 14:52:36.196: W/VideoView(26612): at android.media.MediaPlayer._setVideoSurface(Native Method)
03-21 14:52:36.196: W/VideoView(26612): at android.media.MediaPlayer.setDisplay(MediaPlayer.java:633)
03-21 14:52:36.196: W/VideoView(26612): at android.widget.VideoView.openVideo(VideoView.java:222)
03-21 14:52:36.196: W/VideoView(26612): at android.widget.VideoView.access$2000(VideoView.java:49)
03-21 14:52:36.196: W/VideoView(26612): at android.widget.VideoView$6.surfaceCreated(VideoView.java:465)
03-21 14:52:36.196: W/VideoView(26612): at android.view.SurfaceView.updateWindow(SurfaceView.java:533)
03-21 14:52:36.196: W/VideoView(26612): at android.view.SurfaceView.access$000(SurfaceView.java:81)
03-21 14:52:36.196: W/VideoView(26612): at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:169)
03-21 14:52:36.196: W/VideoView(26612): at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590)
03-21 14:52:36.196: W/VideoView(26612): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1617)
03-21 14:52:36.196: W/VideoView(26612): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
03-21 14:52:36.196: W/VideoView(26612): at android.os.Handler.dispatchMessage(Handler.java:99)
03-21 14:52:36.196: W/VideoView(26612): at android.os.Looper.loop(Looper.java:137)
03-21 14:52:36.196: W/VideoView(26612): at android.app.ActivityThread.main(ActivityThread.java:4424)
03-21 14:52:36.196: W/VideoView(26612): at java.lang.reflect.Method.invokeNative(Native Method)
03-21 14:52:36.196: W/VideoView(26612): at java.lang.reflect.Method.invoke(Method.java:511)
03-21 14:52:36.196: W/VideoView(26612): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-21 14:52:36.196: W/VideoView(26612): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-21 14:52:36.196: W/VideoView(26612): at dalvik.system.NativeStart.main(Native Method)
03-21 14:52:36.196: D/VideoView(26612): Error: 1,0
我正在使用准备好的监听器来调用start:
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer arg0) {
mVideoView.start();
}
});
我用这个设置数据源:
file = new File(this.getFilesDir() + File.separator + VIDEO_FILE_NAME);
mVideoView.setVideoPath(file.getAbsolutePath());
我确定该文件确实存在且格式正确。
我的应用程序可以从警报触发器启动。当设备屏幕关闭时触发器触发并启动我的应用程序似乎只是一个问题(我的应用程序将通过唤醒锁定打开屏幕)。如果我手动启动应用程序,或触发器发生在视频上的屏幕播放正常。这个错误也只发生在Galaxy Nexus上。我可以在Nexus S(以及其他一长串列表)上运行完全相同的代码,并且每次都可以正常运行。
是否有人知道可能导致此行为的Galaxy Nexus或ICS特有的内容?对于我可以尝试修复的内容有什么建议吗?
答案 0 :(得分:7)
UThis已连接到SurfaceView。 在MediaPlayer上调用prepare后,确保没有触摸SurfaceView,并且它是可见的。在您尝试唤醒屏幕的情况下,请确保一切都以正确的顺序发生。因此准备MediaPlayer进行播放是应用程序应该做的最后一件事。可能是应用程序完全唤醒之前启动准备/回放,导致应用程序尝试操作SurfaceView。
以下代码示例说明了如何触发此类异常:
private void setupVideo(String file){
...
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
mHolder = mSurfaceView.getHolder(); // DON'T TOUCH BEHIND THIS POINT
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mMediaPlayer.setDisplay(mHolder);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.prepare();
}
@Override
public void onPrepared(final MediaPlayer mp) {
mSurfaceView.setVisibility(View.VISIBLE); // THIS WILL CAUSE THE ERROR
mp.start();
}
答案 1 :(得分:7)
我对ICS没有名牌有同样的问题。
调用setDisplay方法时不会创建SurfaceHolder,这会导致:
03-21 14:52:36.196: W/VideoView(26612): java.lang.IllegalArgumentException: The surface has been released
要修复它,我使用:
private void setupVideo(String file){
...
mMediaPlayer.setOnPreparedListener(this);
mHolder=mSurfaceView.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.setKeepScreenOn(true);
mHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mHolder=holder;
mMediaPlayer.setDisplay(mHolder);
...
mMediaPlayer.prepare();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) { ... }
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { ... }
});
}
@Override
public void onPrepared(final MediaPlayer mp) {
...
mMediaPlayer.start();
}
答案 2 :(得分:1)
我通过以下实现解决了这个问题。
@Override
protected void onPause()
{
Log.v("MediaVideo", "onPause");
super.onPause();
this.mVideoView.pause();
this.mVideoView.setVisibility(View.GONE);
}
@Override
protected void onDestroy()
{
Log.v("MediaVideo", "onDestroy");
super.onDestroy();
}
@Override
protected void onResume()
{
Log.v("MediaVideo", "onResume");
super.onResume();
this.mVideoView.resume();
}
覆盖OnPause并调用mVideoView.pause()并将设置可见性调用到GONE。 这样我就可以解决“Activity has leaked window”日志错误问题。
答案 3 :(得分:0)
您的Galaxy Nexus是否有机会根据并运行键盘管理器应用程序? 在测试我的应用程序时,我看到了完全相同的堆栈跟踪,并在我的logcat转储中注意到以下行:
06-26 08:42:49.511 I/ActivityManager( 218): START {flg=0x10050000 cmp=com.ne0fhykLabs.android.utility.km/.TransitionDialog} from pid 11150
这是键盘管理器应用程序在屏幕方向改变后立即启动。
一旦我禁用键盘管理器服务,一切都开始与我的视频一起工作。
据我所知,他们都使用相同的SurfaceHolder,当键盘管理器完成后,它被释放,导致VideoView尝试使用它时出现异常。
为了解决这个问题,您可以尝试提到here(网站是中文,但链接已翻译)。我还没有尝试过,但希望它可以工作,因为它使用自己的专用SurfaceView。
答案 4 :(得分:0)
覆盖onpause
和onresume
回调似乎可以解决这个问题,而且只适用于有这个问题的NEXUS Galaxy。