问题
I'm currently creating an app that gets a list of video from an API then plays them sequentially using ExoPlayer
. Yesterday, everything is working fine but now I can't play the videos. The player tries to play the video but gets stuck in buffering state.
To make sure that the videos on our server is not the reason that my app is not working, I looked for a sample mp4 video online and found this. It still didn't play. The answers on the other SO questions didn't work either.
This are the codes I use for initializing ExoPlayer
. I'm using PlayerView
if you guys need that info.
private void initializePlayer() {
if (exoPlayer == null) {
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(trackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
playerView.setPlayer(exoPlayer);
exoPlayer.addListener(exoPlayEventListener);
}
}
This is the code for EventListener
.
Player.EventListener exoPlayEventListener = new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState){
case Player.DISCONTINUITY_REASON_PERIOD_TRANSITION:
Log.d(TAG, "eventListen onPlayerStateChanged DISCONTINUITY_REASON_PERIOD_TRANSITION");
break;
case Player.STATE_BUFFERING:
Log.d(TAG, "Buffering . . . .");
break;
case Player.STATE_READY:
Log.d(TAG, "Ready!!!");
break;
case Player.STATE_ENDED:
Log.d(TAG, "player ended");
playLoopVideo();
break;
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
switch (error.type) {
case ExoPlaybackException.TYPE_SOURCE:
Log.d(TAG, "ERR TYPE_SOURCE: " + error.getSourceException().getMessage());
playLoopVideo();
break;
case ExoPlaybackException.TYPE_RENDERER:
Log.d(TAG, "ERR TYPE_RENDERER: " + error.getRendererException().getMessage());
playLoopVideo();
break;
case ExoPlaybackException.TYPE_UNEXPECTED:
Log.d(TAG, "ERR TYPE_UNEXPECTED: " + error.getUnexpectedException().getMessage());
playLoopVideo();
break;
}
}
@Override
public void onPositionDiscontinuity(int reason) {
if (reason == Player.DISCONTINUITY_REASON_PERIOD_TRANSITION) {
}
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
};
This is the code I use for changing the video to play. I call this after I get my video list from the API.
private void playLoopVideo() {
toPlayVidIndex = playedVidIndex;
String toPlayVidURL = "";
if(playedVidIndex == 7 && !isDefaultPlayed){
toPlayVidURL = defaultUrl;
playedVidIndex--;
isDefaultPlayed = true;
}else{
if (playedVidIndex >= vidArrLst.size()){
playedVidIndex = 0;
toPlayVidIndex = playedVidIndex;
}
toPlayVidURL = vidArrLst.get(toPlayVidIndex).getUrl();
isDefaultPlayed = false;
}
startStream(toPlayVidURL);
playedVidIndex++;
}
This is the code for playing the video stream.
private void startStream(String streamLink){
Uri mediaUri = Uri.parse(streamLink);
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(ctx.getApplicationContext(),
Util.getUserAgent(ctx.getApplicationContext(),
"Streamer"), defaultBandwidthMeter);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(mediaUri);
exoPlayer.setPlayWhenReady(true);
exoPlayer.prepare(mediaSource, true, false);
currentStreamMediaSource = mediaSource;
}
In onStop()
and onDestroy()
, I call this code for releasing the player.
private void releasePlayer() {
if (exoPlayer != null) {
playbackPosition = exoPlayer.getCurrentPosition();
currentWindow = exoPlayer.getCurrentWindowIndex();
playWhenReady = exoPlayer.getPlayWhenReady();
exoPlayer.release();
exoPlayer = null;
}
}
This is my build.gradle(app) if you need it.
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "biz.net.com.streamer"
minSdkVersion 17
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.google.android.exoplayer:exoplayer:2.9.1'
implementation 'com.android.volley:volley:1.1.1'
}
UPDATE:
Today, I tried to directly play a video using my startStream method and it played the sample mp4 video and a video from our server.
This the code I use for getting our local video API. For some reason, if I play the videos inside that method it won't play but directly using startStream() plays the videos.
public void getVideoAds(String serverURL){
String url = "http://"+serverURL+"/video/";
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, "getVidAds res: "+response);
try {
JSONObject jsonObj = new JSONObject(response);
JSONObject defaultObj = jsonObj.getJSONObject("default");
JSONArray videoObj = jsonObj.getJSONArray("videos");
defaultUrl = defaultObj.getString("url");
for (int i = 0; i < videoObj.length(); i++){
JSONObject video = videoObj.getJSONObject(i);
VideoAd v = new VideoAd();
v.setName(getVideoNameFromLink(video.getString("url")));
v.setUrl(video.getString("url"));
v.setVideoId(video.getInt("id"));
v.setVersion(video.getInt("version"));
v.setLocalPath("");
vidArrLst.add(v);
}
playLoopVideo();
} catch (Exception e) {
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "getVidAds err: " + error.getMessage());
}
});
queue.add(stringRequest);
}
UPDATE:
Hi, I made another SO question here about how Volley sometimes doesn't work properly and [a bit weird] affects ExoPlayer
to be stuck on a BUFFERING state. If you want to know more, please look at the other question because I don't want to repeat everything I posted there here.
来源:https://stackoverflow.com/questions/55277277/exoplayer-not-playing-anymore-stuck-on-player-state-buffering