2017-05-11 3 views
0

Ich verwende Exoplayer, um HLS-Video in meiner App zu spielen. Das Problem ist, dass ich BehindLiveWindowException bekomme und ich eine Lösung gefunden habe, Spieler neu zu initialisieren, wenn diese Ausnahme auftritt. Aber irgendwie kann ich diese Ausnahme in meiner Klasse nicht verstehen, damit ich den Player reinitialisieren kann.ExoPlayer - Kann nicht fangen BehindLiveWindowException

Stattdessen kann ich BLWE Ausnahme in Logcat sehen, aber ein Neustart des Players tritt nie auf.

Bitte kann mir jemand sagen, was mache ich falsch, ist mein Code-Schnipsel hier:

public class MainViewModel extends BaseObservable implements ExoPlayer.EventListener { 

private static final String MAIN_VIEWMODEL_TAG = "MAIN_VIEWMODEL"; 
private static MainViewModel mainViewModel; 
private final Context context; 
private final Realm realm; 
private LinearLayoutManager mLinearLayoutManager; 
private List<ChannelRCV> channelRCVList; 
private ChannelRecyclerViewAdapter recyclerViewAdapter; 
private ChannelRCV currentChannelRCV; 
private SimpleExoPlayer player; 
private Handler mainHandler; 
private BandwidthMeter bandwidthMeter; 
private TrackSelection.Factory videoTrackSelectionFactory; 
private TrackSelector trackSelector; 
private LoadControl loadControl; 
private DataSource.Factory dataSourceFactory; 
private MediaSource videoSource; 
private PlayerHelper playerHelper; 


//TODO CONSTRUCTOR MainViewModel 
private MainViewModel(Context context) { 
    this.context = context; 
    recyclerViewAdapter = new ChannelRecyclerViewAdapter(); 

    //channelRCVList = convertList(dbHelper.getWebTvChannelDao().loadAll()); 
    //currentChannelRCV = channelRCVList.get(0); 

    realm = Realm.getDefaultInstance(); 


    //Log.i(MAIN_VIEWMODEL_TAG, "DB IS EMPTY: "+ realm.isEmpty()); 
    channelRCVList = Converter.convertList(realm.where(WebTvChannel.class).findAll()); 

    ForTest forTest = new ForTest(); 

    forTest.test1(); 

    Log.i(MAIN_VIEWMODEL_TAG, channelRCVList.size() + ""); 
    currentChannelRCV = channelRCVList.get(0); 
    recyclerViewAdapter.setList(channelRCVList); 
    recyclerViewAdapter.notifyDataSetChanged(); 
    downloadEpgScheduler(); 

} 

public static MainViewModel getInstance(Context context) { 

    if (mainViewModel == null) { 
     mainViewModel = new MainViewModel(context); 
     mainViewModel.setupPlayer(); 
     return mainViewModel; 
    } else 
     return mainViewModel; 
} 

private static boolean isBehindLiveWindow(ExoPlaybackException e) { 
    if (e.type != ExoPlaybackException.TYPE_SOURCE) { 
     return false; 
    } 
    Throwable cause = e.getSourceException(); 
    while (cause != null) { 
     if (cause instanceof BehindLiveWindowException) { 
      return true; 
     } 
     cause = cause.getCause(); 
    } 
    return false; 
} 

private List<ChannelRCV> convertList(List<WebTvChannel> webTvChannels) { 
    List<ChannelRCV> channelRCVs = new ArrayList<>(); 
    for (WebTvChannel ch : webTvChannels) { 
     channelRCVs.add(new ChannelRCV(ch.getName(), ch.getUrl())); 
    } 

    return channelRCVs; 
} 

@Bindable 
public SimpleExoPlayer getPlayer() { 
    return player; 
} 

public void setPlayer(SimpleExoPlayer player) { 

    this.player = player; 

    notifyPropertyChanged(BR.player); 
} 

public void setupPlayer() { 
    //System.out.println(player); 
    if (player != null) { 

     //player.clearVideoSurface(); 

     player.release(); 

    } 

    mainHandler = new Handler(); 
    bandwidthMeter = new DefaultBandwidthMeter(); 

    videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); 
    trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); 
    loadControl = new DefaultLoadControl(); 

    player = ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl, null, SimpleExoPlayer.STATE_BUFFERING); 

    DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter(); 
    dataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "AOC"), defaultBandwidthMeter); 
    videoSource = new HlsMediaSource(Uri.parse(currentChannelRCV.getUrl()), dataSourceFactory, mainHandler, new AdaptiveMediaSourceEventListener() { 
     @Override 
     public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) { 
      Log.i(MAIN_VIEWMODEL_TAG,"onLoadStarted"); 
     } 

     @Override 
     public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { 
      Log.i(MAIN_VIEWMODEL_TAG,"onLoadCompleted"); 
     } 

     @Override 
     public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onLoadCanceled"); 
     } 

     @Override 
     public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onLoadError2"); 
      player.release(); 
      setupPlayer(); 
     } 

     @Override 
     public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onUpstreamDiscarded"); 
     } 

     @Override 
     public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onDownstreamFormatChanged"); 
     } 

    }); 

    player.prepare(videoSource); 

    player.setPlayWhenReady(true); 

    setPlayer(player); 


} 

public void changeChannel(ChannelRCV channelRCV) { 

    if (channelRCV.getUrl() == null) { 
     Toast.makeText(context, "No resoureces for this channel", Toast.LENGTH_SHORT).show(); 
     return; 
    } 

    videoSource = new HlsMediaSource(Uri.parse(currentChannelRCV.getUrl()), dataSourceFactory, mainHandler, new AdaptiveMediaSourceEventListener() { 
     @Override 
     public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) { 
      Log.i(MAIN_VIEWMODEL_TAG,"onLoadStarted"); 
     } 

     @Override 
     public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { 
      Log.i(MAIN_VIEWMODEL_TAG,"onLoadCompleted"); 
     } 

     @Override 
     public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onLoadCanceled"); 
     } 

     @Override 
     public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) { 
      setupPlayer(); 
      Log.e("onLoadError", "ERROR 1"); 
      Log.e("onLoadError", error.toString()); 
      Log.i(MAIN_VIEWMODEL_TAG, "onLoadError1"); 

     } 

     @Override 
     public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onDownstreamFormatChanged"); 

     } 

     @Override 
     public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) { 
      Log.i(MAIN_VIEWMODEL_TAG, "onDownstreamFormatChanged"); 
     } 

    }); 
    player.prepare(videoSource); 
    player.setPlayWhenReady(true); 
    setPlayer(player); 

} 

public ChannelRecyclerViewAdapter getRecyclerViewAdapter() { 
    return recyclerViewAdapter; 
} 

public LinearLayoutManager getLinearLayoutManager() { 

    mLinearLayoutManager = new LinearLayoutManager(context); 
    mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); 
    mLinearLayoutManager.setSmoothScrollbarEnabled(true); 
    return mLinearLayoutManager; 
} 

public int fullscreen() { 
    return WindowManager.LayoutParams.FLAG_FULLSCREEN; 
} 

public void onClick(View view, ChannelRCV channelRCV) { 
    //view.setBackgroundColor(Color.parseColor("#FFFFFF")); 
    currentChannelRCV = channelRCV; 
    changeChannel(channelRCV); 
} 

// TODO Scheduler 
private void downloadEpgScheduler() { 

    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 

    scheduler.scheduleAtFixedRate(new Runnable() { 
     public void run() { 

      //code goes here 
      Log.i(MAIN_VIEWMODEL_TAG, "SCHEDULER STARTED"); 
      Intent download = new Intent(context, ScheduledDownloadEpgService.class); 
      download.putExtra("package", "AT - WebTV"); 
      // 
      // context.startService(download); 

     } 
    }, 0, 5, TimeUnit.MINUTES); 
} 

private void indirectChannelChange() { 
    changeChannel(currentChannelRCV); 
} 

public void updateRecyclerViewList(List<ChannelRCV> channelRCVs) { 

    channelRCVList = channelRCVs; 
    recyclerViewAdapter.setList(channelRCVs); 
    changeChannel(channelRCVs.get(0)); 
    recyclerViewAdapter.notifyDataSetChanged(); 
    player.release(); 
    setupPlayer(); 

} 

@Override 
public void onTimelineChanged(Timeline timeline, Object manifest) { 
    Log.e("onTimelineChanged", "onTimelineChanged"); 

} 

@Override 
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { 
    Log.e("onTracksChanged", "onTracksChanged"); 

} 

@Override 
public void onLoadingChanged(boolean isLoading) { 
    Log.i("onLoadingChanged", "Loading Changed"); 
} 

@Override 
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { 
    Log.i("onPlayerStateChanged", "Player State Changed"); 
} 

@Override 
public void onPlayerError(ExoPlaybackException error) { 
    //System.out.println("///////////////////////////////////////////////////////////////////// onPlayerError"); 
    Log.e("OnPlayerError", "Error ExoPlayer"); 
    if (isBehindLiveWindow(error)) { 
     Log.e("OnPlayerError", "starting again"); 

     player.release(); 
     setupPlayer(); 

     //changeChannel(currentChannelRCV); 
    } 
} 


@Override 
public void onPositionDiscontinuity() { 
    Log.i(MAIN_VIEWMODEL_TAG, "onPositionDiscontinuity"); 
} 

@Override 
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { 
    Log.i("onPlaybackParamChanged", "Player State Changed"); 
} 

public void stopPlayer() { 
    player.stop(); 
    player.release(); 

} 

public void setVodUrl(String url) { 


}} 

Dank

Antwort

0

ich die Lösung gefunden zu haben! Stattdessen ExoPlayer.EventListener zu implementieren ich wie folgt zu exoPlayer Listener-Objekt gerade hinzugefügt:

exoPlayer.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) { 
       Log.e(PLAYER_ACTIVITY_TAG, "SOME ERROR IN PLAYER"); 
       if (isBehindLiveWindow(error)) { 
        setupPlayer(); 
       } 
      } 

      @Override 
      public void onPositionDiscontinuity() { 

      } 

      @Override 
      public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { 

      } 
     }); 

und Verfahren isBehindLiveWindow

private static boolean isBehindLiveWindow(ExoPlaybackException e) { 
     if (e.type != ExoPlaybackException.TYPE_SOURCE) { 
      return false; 
     } 
     Throwable cause = e.getSourceException(); 
     while (cause != null) { 
      if (cause instanceof BehindLiveWindowException) { 
       return true; 
      } 
      cause = cause.getCause(); 
     } 
     return false; 
    } 

Nun, wenn Fehler Player automatisch neu gestartet werden auftritt.