如何捕获ExoPlayer的所有错误?

17
我在我的应用程序中使用 ExoPlayer 作为播放器。但我不知道如何捕获所有 ExoPlayer 错误以避免应用程序崩溃。我添加了以下监听器,但它并不能捕获所有错误。
由于我必须使用DRM,有时会出现问题导致崩溃,但是我不能在播放器为空之前设置监听器。
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl, drmSessionManager);

player.addListener(new ExoPlayer.EventListener() {
    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest) {

    }

    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

    }

    @Override
    public void onLoadingChanged(boolean isLoading) {

    }

    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {

    }

    @Override
    public void onPlayerError(ExoPlaybackException error) {
    //Catch here, but app still crash on some errors!
    }

    @Override
    public void onPositionDiscontinuity() {

    }
});

错误示例:

03-22 16:38:31.401 17960-25624/com.mypackage.name E/ExoPlayerImplInternal: Renderer error.  
com.google.android.exoplayer2.ExoPlaybackException  
    at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:709)   
    at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:650) 
    at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:490)  
    at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:464)   
    at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300)    
    at android.os.Handler.dispatchMessage(Handler.java:98)  
    at android.os.Looper.loop(Looper.java:154)  
    at android.os.HandlerThread.run(HandlerThread.java:61)  
    at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)  
Caused by: com.google.android.exoplayer2.drm.DrmSession$DrmSessionException: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to https://widevine-dash.ezdrm.com/proxy?pX=blablablabla  
    at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:594)    
    at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:589)    
    at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:549)  
    at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:49)  
    at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:669)  
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:154)  
    at android.os.HandlerThread.run(HandlerThread.java:61)  
    at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)  
Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to https://widevine-dash.ezdrm.com/proxy?pX=blablablabla    
    at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:204)    
    at com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:101) 
    at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:81) 
    at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:75) 
    at com.google.android.exoplayer2.util.Util.toByteArray(Util.java:118)   
    at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:106)    
    at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:91)   
    at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:692)   
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:154)  
    at android.os.HandlerThread.run(HandlerThread.java:61)  
Caused by: java.net.SocketTimeoutException: timeout 
    at com.android.okhttp.okio.Okio$3.newTimeoutException(Okio.java:212)    
    at com.android.okhttp.okio.AsyncTimeout.exit(AsyncTimeout.java:250) 
    at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:217)   
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:306)  
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:300)  
    at com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:196)   
    at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:191)    
    at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:80)    
    at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:906) 
    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:782)    
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:463)    
   03-22 16:38:31.401 17960-25624/com.mypackage.name E/ExoPlayerImplInternal:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:405)  
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:521)    
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)  
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java)  
    at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:201)    
        ... 10 more
   03-22 16:38:31.402 17960-17960/com.mypackage.name E/PlayerActivity: onPlayerError: com.google.android.exoplayer2.drm.DrmSession$DrmSessionException: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to https://widevine-dash.ezdrm.com/proxy?pX=blablablabla   
   03-22 16:38:31.404 17960-17960/com.mypackage.name D/AndroidRuntime: Shutting down VM 
   03-22 16:38:31.407 17960-17960/com.mypackage.name E/UncaughtException: java.lang.IllegalStateException   
at com.google.android.exoplayer2.util.Assertions.checkState(Assertions.java:79) 
at com.google.android.exoplayer2.ExoPlaybackException.getSourceException(ExoPlaybackException.java:111) 
at com.mypackage.name.ui.activities.PlayerActivity$1.onPlayerError(PlayerActivity.java:260) 
at com.google.android.exoplayer2.ExoPlayerImpl.handleEvent(ExoPlayerImpl.java:382)  
at com.google.android.exoplayer2.ExoPlayerImpl$1.handleMessage(ExoPlayerImpl.java:93)   
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154)  
at android.app.ActivityThread.main(ActivityThread.java:6121)    
at java.lang.reflect.Method.invoke(Native Method)   
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)  
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 
   03-22 16:38:31.417 17960-25623/com.mypackage.name D/FA: Logging event (FE): _ae, Bundle[{_o=crash, _sc=PlayerActivity_, _si=-5050973009208192093, timestamp=1490197111407, fatal=1}] 
   03-22 16:38:31.437 17960-25684/com.mypackage.name D/SurfaceUtils: set up nativeWindow 0x791072a810 for 1x1, color 0x2, rotation 0, usage 0x930   
   03-22 16:38:31.454 17960-25623/com.mypackage.name V/FA: Using measurement service    
   03-22 16:38:31.455 17960-25623/com.mypackage.name V/FA: Connecting to remote service 
   03-22 16:38:31.707 17960-17960/com.mypackage.name E/AndroidRuntime: FATAL EXCEPTION: main    
     Process: com.mypackage.name, PID: 17960    
     java.lang.IllegalStateException    
         at com.google.android.exoplayer2.util.Assertions.checkState(Assertions.java:79)    
         at com.google.android.exoplayer2.ExoPlaybackException.getSourceException(ExoPlaybackException.java:111)    
         at com.mypackage.name.ui.activities.PlayerActivity$1.onPlayerError(PlayerActivity.java:260)    
         at com.google.android.exoplayer2.ExoPlayerImpl.handleEvent(ExoPlayerImpl.java:382) 
         at com.google.android.exoplayer2.ExoPlayerImpl$1.handleMessage(ExoPlayerImpl.java:93)  
         at android.os.Handler.dispatchMessage(Handler.java:102)    
         at android.os.Looper.loop(Looper.java:154) 
         at android.app.ActivityThread.main(ActivityThread.java:6121)   
         at java.lang.reflect.Method.invoke(Native Method)  
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

请提供准确的错误信息和堆栈跟踪。 - Okas
请检查更新后的问题。 - Michalsx
4个回答

30

多亏了来自ExoPlayer支持团队的反馈,这应该涵盖了所有问题。

    @Override
    public void onPlayerError(ExoPlaybackException error) {
        switch (error.type) {
            case ExoPlaybackException.TYPE_SOURCE:
                Log.e(TAG, "TYPE_SOURCE: " + error.getSourceException().getMessage());
                break;

            case ExoPlaybackException.TYPE_RENDERER:
                Log.e(TAG, "TYPE_RENDERER: " + error.getRendererException().getMessage());
                break;

            case ExoPlaybackException.TYPE_UNEXPECTED:
                Log.e(TAG, "TYPE_UNEXPECTED: " + error.getUnexpectedException().getMessage());
                break;
        }
    }

你为这个方法实现了哪个接口? - A_rmas
2
@A_rmas 它是com.google.android.exoplayer2.Player#EventListener - Sermilion

6
您可以像这样捕获ExoPlayer错误:
this.player = new SimpleExoPlayer.Builder(PlayActivity.this).build();

player.addListener(new Player.EventListener() {
                @Override
                public void onPlayerError(ExoPlaybackException error) {
                    .....
                }
});

4
Player.EventListener 已经被弃用,您可以使用 Player.Listener 来代替。 - cges30901
1
是的,它必须是Player.Listener,但现在参数是PlaybackException,它不再具有我需要的rendererIndex属性。使用需要2%d的错误消息资源lb_media_player_error。有人知道在哪里找到rendererIndex吗? - chitgoks
SimpleExoPlayer 已被弃用,请使用 ExoPlayer 替代。 - James
是的,它已经被弃用了,但如何将现有的实现从 onPlayerError(ExoPlaybackException e) 迁移到 onPlayerError(PlaybackException e)? ExoPlayer 或其他人有任何文档或线索吗? - Nadimuddin

3

对于Kotlin用户来说,语法有些不同(我在对象声明方面遇到了困难):

// initialize and setup exo player
player = SimpleExoPlayer.Builder(applicationContext).build()
// setup error listener
player.addListener(object : Player.EventListener {
    override fun onPlayerError(error: ExoPlaybackException) {
    log.debug("ExoPlayer error, ${error.sourceException.message}")
    }
})

2
作为 @deprecated 的 Event Listener 现在你可以调用 Listener。
Kotlin
var exoPlayer = SimpleExoPlayer.Builder(context).build()

exoPlayer?.addListener(object : Player.Listener {
        override fun onPlayerError(error: ExoPlaybackException) {
            when(error.type){
                ExoPlaybackException.TYPE_REMOTE -> {
                    Utils.appToast(
                        requireActivity(),
                        error.localizedMessage
                    )
                }
                ExoPlaybackException.TYPE_RENDERER -> {
                    Utils.appToast(
                        requireActivity(),
                        error.rendererException.message
                    )
                }
                ExoPlaybackException.TYPE_SOURCE -> {
                    Utils.appToast(
                        requireActivity(),
                        error.sourceException.message
                    )
                }
                ExoPlaybackException.TYPE_UNEXPECTED -> {
                    Utils.appToast(
                        requireActivity(),
                        error.unexpectedException.message
                    )
                }
            }
        }
    })

在初始化播放器函数中。
private fun initializePlayer() {

    bi.exoVideoPlayer.player = exoPlayer
            .......
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接