2013-10-30 29 views
1

让MediaPlayer在Android 4.3(以及更低版本)上可靠地播放视频时遇到了一些麻烦。大部分代码只是标准样板(包括完整性)。在MediaPlayer中使用ZipFileProvider有时会导致IllegalStateException

我使用APK扩展库,而我的obb只是som缩略图和一些m4v视频文件的zip文件,以及用于描述视频的XML文件。

我认为有一个计时问题,因为错误似乎只发生在播放小文件(< 30秒或在我的情况下< 3Mb)。下面的代码运行mMediaPlayer.prepare()当它发生:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 

    setContentView(R.layout.activity_play_video); 
    Intent intent = getIntent(); 
    mFileName = intent.getStringExtra("Video"); //which video should we play 
    ... 
    mHolder = mSurfaceView.getHolder(); 
    mHolder.addCallback(this); 
} 


@Override 
public void surfaceCreated(SurfaceHolder holder) { 
      playVideo(); 
} 


public void playVideo() { 
    String videoFilePath = Const.CONTENT_URI + "/" + mFileName + ".m4v"; 
    Uri zipVideo = Uri.parse(videoFilePath); 

    mMediaPlayer = new MediaPlayer(); 
    try { 
     mMediaPlayer.setDataSource(getApplicationContext(), zipVideo); 
     mMediaPlayer.setDisplay(mHolder); 
     mMediaPlayer.prepare(); 
     mMediaPlayer.setOnPreparedListener(this); 
     mMediaPlayer.setOnErrorListener (new MediaPlayer.OnErrorListener() { 
      @Override 
      public boolean onError(MediaPlayer mp, int what, int extra) { 
       Log.d("ERROR", "what: " + what + " extra: " + extra); 
       return false; 
      } 
     }); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (IllegalStateException e) { 
     e.printStackTrace(); 
     finish(); 
    } 
    ... 
} 

@Override 
public void onPrepared(MediaPlayer mp) { 
    Log.d("playback " , "onPrepared"); 
    start(); 
} 

我一直在调查这个问题,似乎setDataSource(...)不设置的mMediaPlayerprepare()前的正确状态被调用。

是什么让这个问题更加有趣的是,当播放较大的文件时,它的工作完美无瑕。

编辑: 这里logcat的输出。

11-01 13:19:12.483: E/MediaPlayer(26369): prepareAsync called in state 1 
11-01 13:19:12.483: W/System.err(26369): java.lang.IllegalStateException 
11-01 13:19:12.483: W/System.err(26369): at android.media.MediaPlayer.prepare(Native Method) 
11-01 13:19:12.483: W/System.err(26369): at com.skilessons4u.lite.PlayVideoActivity.prepareVideo(PlayVideoActivity.java:126) 
11-01 13:19:12.483: W/System.err(26369): at com.skilessons4u.lite.PlayVideoActivity.surfaceCreated(PlayVideoActivity.java:100) 
11-01 13:19:12.483: W/System.err(26369): at android.view.SurfaceView.updateWindow(SurfaceView.java:571) 
11-01 13:19:12.483: W/System.err(26369): at android.view.SurfaceView.access$000(SurfaceView.java:86) 
11-01 13:19:12.483: W/System.err(26369): at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:175) 
11-01 13:19:12.483: W/System.err(26369): at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:833) 
11-01 13:19:12.483: W/System.err(26369): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1860) 
11-01 13:19:12.483: W/System.err(26369): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1004) 
11-01 13:19:12.483: W/System.err(26369): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5481) 
11-01 13:19:12.483: W/System.err(26369): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 
11-01 13:19:12.483: W/System.err(26369): at android.view.Choreographer.doCallbacks(Choreographer.java:562) 
11-01 13:19:12.483: W/System.err(26369): at android.view.Choreographer.doFrame(Choreographer.java:532) 
11-01 13:19:12.483: W/System.err(26369): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) 
11-01 13:19:12.483: W/System.err(26369): at android.os.Handler.handleCallback(Handler.java:730) 
11-01 13:19:12.483: W/System.err(26369): at android.os.Handler.dispatchMessage(Handler.java:92) 
11-01 13:19:12.483: W/System.err(26369): at android.os.Looper.loop(Looper.java:137) 
11-01 13:19:12.483: W/System.err(26369): at android.app.ActivityThread.main(ActivityThread.java:5103) 
11-01 13:19:12.483: W/System.err(26369): at java.lang.reflect.Method.invokeNative(Native Method) 
11-01 13:19:12.483: W/System.err(26369): at java.lang.reflect.Method.invoke(Method.java:525) 
11-01 13:19:12.483: W/System.err(26369): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 
11-01 13:19:12.483: W/System.err(26369): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
11-01 13:19:12.483: W/System.err(26369): at dalvik.system.NativeStart.main(Native Method) 

为了完整起见,这里是我在脚本中运行的命令来生成obb文件。缩略图显示出很好,很强硬。

zip -rn .m4v:.png $ZIPFILE $XMLFILE $VIDEOSDIR $THUMBDIR 
zipalign 4 $ZIPFILE $OBBFILE 
+0

你可以发布在LogCat上看到的错误,这可能会有所帮助。 –

+0

我已经包含了logcat输出。 – DansMedLasse

回答

0

我能得到这个工作,通过使用AssetFileDescriptor,而不是一个开放的

,最终解决我的问题是做了以下的方法:

AssetFileDescriptor afd = expansionFile.getAssetFileDescriptor(mFileName + ".m4v"); 
FileDescriptor fd = afd.getFileDescriptor(); 
long offset = afd.getStartOffset(); 
long length = afd.getLength(); 

try { 
    mMediaPlayer = new MediaPlayer(); 
    mMediaPlayer.setDataSource(fd,offset, length); 
    mMediaPlayer.prepare(); 
... 
} catch (IOException e) { 
    e.printStackTrace(); 
} catch (IllegalStateException e) { 
    e.printStackTrace(); 
} 

我已经试过了之前的方法,但没有偏移和长度参数,并没有工作。你上面看到的是最终得到它的工作。

我的错误的方法之前,使用“ZipFileContentProvider”像这样:

public final static String AUTHORITY = "com.example.app.provider.ZipFileContentProvider"; 
public final static Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); 

String videoFilePath = CONTENT_URI + "/" + mFileName + ".m4v"; 
Uri zipVideo = Uri.parse(videoFilePath); 
mMediaPlayer = new MediaPlayer(); 
mMediaPlayer.setDataSource(this, zipVideo); 
mMediaPlayer.setDisplay(mHolder); 
mMediaPlayer.prepare(); 

然而,由于在原来的问题mentionend,这只是在某些特定情况下,这是很不理想的工作。

相关问题