Stop exo player video from playing when exit from activity android - android

I am using Exo-Player.My video is playing fine but when i press back button and exit from activity my video keeps on playing in background.I don't how to stop it from playing when activity is finished.Please help
This is my code for exo player in recycler view adaptor
String my_date = data.get(position).getCreated_at();
String returneDate = setDateAndTime(my_date);
String img_url = data.get(position).getUser().getProfileUrl();
String videoUrl = data.get(position).getFile_url();
if (videoUrl != null) {
uri = Uri.parse(videoUrl);
} else {
holder.videoFrame.setVisibility(View.GONE);
}
holder.userVideoStatus.setText(data.get(position).getText());
holder.userNameVideoStatus.setText((CharSequence) data.get(position).getUser().getName());
holder.timeVideoStatus.setText(returneDate);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelector trackSelector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory(bandwidthMeter));
player = ExoPlayerFactory.newSimpleInstance(activity, trackSelector);
DefaultHttpDataSourceFactory defaultHttpDataSourceFactory = new DefaultHttpDataSourceFactory("exo player");
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
final MediaSource mediaSource = new ExtractorMediaSource(uri, defaultHttpDataSourceFactory, extractorsFactory, null, null);
holder.playVideo.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
holder.playVideo.setVisibility(View.GONE);
holder.userVideoUpdate.setPlayer(player);
player.prepare(mediaSource);
player.setPlayWhenReady(true);
holder.volumeUp.setVisibility(View.VISIBLE);
return true;
}
});

Ok Pavel B. gave the right answer but I am elaborating and making it clearer...
Adapter
public class ChatsAdapter extends RecyclerView {
public SimpleExoPlayer exoPlayer; // Do this at top
}
Activity
public class TestActivity extends AppCompatActivity {
private ChatsAdapter chatsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
chatsAdapter = new ChatsAdapter();
}
#Override
protected void onPause() {
super.onPause();
pausePlayer(chatsAdapter.exoPlayer);
}
#Override
protected void onStop() {
super.onStop();
pausePlayer(chatsAdapter.exoPlayer);
}
#Override
protected void onDestroy() {
super.onDestroy();
releaseExoPlayer(chatsAdapter.exoPlayer);
}
#Override
protected void onResume() {
super.onResume();
startPlayer(chatsAdapter.exoPlayer);
}
public static void startPlayer(SimpleExoPlayer exoPlayer) {
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(true);
}
}
public static void pausePlayer(SimpleExoPlayer exoPlayer) {
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(false);
}
}
public static void releaseExoPlayer(SimpleExoPlayer exoPlayer) {
if (exoPlayer != null) {
exoPlayer.release();
}
}
}

in Your adapter - make player a public class member.
in Your activivty onStop() add:
yourAdapter.player.stopPlayback();

If you want to stop exoplayer , upgrade the latest Version of exoplayer and then try using
implementation 'com.google.android.exoplayer:exoplayer:2.14.2'
I tried using playerview.OnPause but that doesnt work .
player.setPlayWhenReady(true) - Used to Pause the player
player.setPlayWhenReady(false) - Used to Resume player .
Make sure you get the same instance of exoplayer everywhere , better if you can make a singleton class.

Related

SimpleExoPlayer doesn't stream for the second time

I want to play a radio channel from url by using SimpleExoPlayer, the code works only for the first time, i.e., when I press play it works, then I press again it stops. But if I press again play button it doesn't play.
I tried to delete cache in every stop event but it also didn't solve the problem.
public class MainActivity extends AppCompatActivity {
private String source;
private SimpleExoPlayer simpleExoPlayer;
private boolean isPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton btnPlay = findViewById(R.id.image_play);
source = "http://mp3stream7.apasf.apa.at/stream/1/";
isPlaying = false;
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isPlaying) {
setupPlayer();
simpleExoPlayer.setPlayWhenReady(true);
isPlaying = true;
} else {
simpleExoPlayer.stop();
simpleExoPlayer.setPlayWhenReady(false);
isPlaying = false;
}
}
});
}
private void setupPlayer() {
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(MainActivity.this, null,
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);
TrackSelector trackSelector = new DefaultTrackSelector();
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);
String userAgent = Util.getUserAgent(MainActivity.this, "Play Audio");
ExtractorMediaSource mediaSource = new ExtractorMediaSource(Uri.parse(source),
new CacheDataSourceFactory(MainActivity.this, 100 * 1024 * 1024, 5 * 1024 * 1024),
new DefaultExtractorsFactory(), null, null);
simpleExoPlayer.prepare(mediaSource);
}
private void release_player() {
simpleExoPlayer.release();
}
#Override
protected void onDestroy() {
simpleExoPlayer.release();
super.onDestroy();
}
#Override
protected void onPause() {
simpleExoPlayer.release();
super.onPause();
}
}
try this:
public class MainActivity extends AppCompatActivity {
private String source;
private SimpleExoPlayer simpleExoPlaye = null;
private boolean isPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton btnPlay = findViewById(R.id.image_play);
source = "http://mp3stream7.apasf.apa.at/stream/1/";
isPlaying = false;
//add this
setupPlayer();
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isPlaying) {
//remove setupPlayer(); from here
simpleExoPlayer.setPlayWhenReady(true);
isPlaying = true;
} else {
//remove simpleExoPlayer.stop(); from here
simpleExoPlayer.setPlayWhenReady(false);
isPlaying = false;
}
}
});
}
#Override
public void onResume() {
super.onResume();
if (simpleExoPlayer != null) {
simpleExoPlayer.setPlayWhenReady(isPlaying);
} else {
setupPlayer();
}
}
private void setupPlayer() {
if (simpleExoPlayer != null) {
simpleExoPlayer.stop();
}
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(MainActivity.this, null,
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);
TrackSelector trackSelector = new DefaultTrackSelector();
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);
String userAgent = Util.getUserAgent(MainActivity.this, "Play Audio");
ExtractorMediaSource mediaSource = new ExtractorMediaSource(Uri.parse(source),
new CacheDataSourceFactory(MainActivity.this, 100 * 1024 * 1024, 5 * 1024 * 1024),
new DefaultExtractorsFactory(), null, null);
simpleExoPlayer.prepare(mediaSource);
}
#Override
protected void onDestroy() {
//remove releaze from onDestroy and onPause
simpleExoPlayer.stop();
super.onDestroy();
}

Exoplayer audio playing background even video was closed

Below is My fragment that contains exoplayer which will inflate with draggable panel in Activity. My problem is while swiping the draggable panel left or right video is closing but audio is still playing in background. If I swipe off the draggable panel audio also needs to closed.Tried many sources couldn't found any solutions.Also In both fragment and Activity while swipping off the draggable panel onPause() method is not triggred. Also public void onClosedToLeft() method also not getting called.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dragpanelone, container, false);
try {
exoPlayerView = (SimpleExoPlayerView)v.findViewById(R.id.exoplayer);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelector trackSelector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory(bandwidthMeter));
exoplayer = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector);
Uri uri = Uri.parse(videoURL);
DefaultHttpDataSourceFactory dataSourceFactory = new DefaultHttpDataSourceFactory("exoplayer_video");
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory, null, null);
exoPlayerView.setPlayer(exoplayer);
exoplayer.prepare(mediaSource);
exoplayer.setPlayWhenReady(true);
} catch (Exception e){
e.printStackTrace();
}
return v;
}
#Override
public void onDestroy() {
super.onDestroy();
exoplayer.release();
}
#Override
public void onStop() {
super.onStop();
exoplayer.setPlayWhenReady(false);
}
public void pausePlayback() {
exoplayer.setPlayWhenReady(false); //pauses the playback if it's playing
}
private void releasePlayer() {
if (exoplayer != null) {
exoplayer.release();
exoplayer.setPlayWhenReady(false);
exoplayer = null;
}
}
public static void closePlayer()
{
exoplayer.clearVideoSurface();
}
}
This is my Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeDraggablepanel();
hookDraggablePanelListners();
}
public void initializeDraggablepanel(){
draggablepanel = (DraggablePanel)findViewById(R.id.draggable_panel);
draggablepanel.setFragmentManager(getSupportFragmentManager());
draggablepanel.setTopFragment(new DragpanelFragOne());
draggablepanel.setBottomFragment(new DragPanelTwo());
draggablepanel.setTopViewHeight(550);
draggablepanel.initializeView();
}
private void hookDraggablePanelListners(){
draggablepanel.setDraggableListener(new DraggableListener() {
#Override
public void onMaximized() {
}
#Override
public void onMinimized() {
}
#Override
public void onClosedToLeft() {
DragpanelFragOne.closePlayer();
Intent i = new Intent(MainActivity.this,HomeScreen.class);
startActivity(i);
}
#Override
public void onClosedToRight() {
DragpanelFragOne.closePlayer();
Intent i = new Intent(MainActivity.this,HomeScreen.class);
startActivity(i);
}
});
}
#Override
public void onPause() {
super.onPause();
DragpanelFragOne.closePlayer();
}
#Override
public void onStop() {
super.onStop();
draggablepanel.closeToLeft();
}
#Override
public void onBackPressed() {
draggablepanel.isClickToMinimizeEnabled();
Intent i = new Intent(MainActivity.this,HomeScreen.class);
startActivity(i);
}
}
Solution:
You need to call the method stop() on the exoplayer object whenever you are closing the player, like this:
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(false);
exoPlayer.stop();
exoPlayer.seekTo(0);
}
Hope this helps.

Pause ExoPlayer when headphones unplugged

How do I change the playback state of ExoPlayer when the Broadcast receiver is triggered?
I have a BroadcastReceiver that gets triggered when the headset is disconnected however I am not sure of the correct way to handle the pausing of audio when onReceive() is called. Do I need to change the playback state of the Mediasession here?
private static final int CORRECT_ANSWER_DELAY_MILLIS = 1000;
public static final String TAG = QuizActivity.class.getSimpleName();
private SimpleExoPlayer mExoPlayer;
private PlayerView mPlayerView;
private PlayerListener mPlayerListener;
private PlaybackStateCompat.Builder mPlaybackStateBuilder;
public static MediaSessionCompat mMediaSession;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
initializeMediaSession();
mPlayerListener = new PlayerListener();
// Initialize the player view.
mPlayerView = (PlayerView) findViewById(R.id.playerView);
// Initialize the player.
initializePlayer(Uri.parse(answerSample.getUri()));
}
/**
* Initialize ExoPlayer.
*
* #param mediaUri The URI of the sample to play.
*/
// done (2): Set the ExoPlayer.EventListener to this activity
private void initializePlayer(Uri mediaUri) {
// 1. Create a default TrackSelector
if (mExoPlayer == null) {
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
DefaultTrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create the player
mExoPlayer =
ExoPlayerFactory.newSimpleInstance(this, trackSelector);
mExoPlayer.addListener(mPlayerListener);
mPlayerView.setPlayer(mExoPlayer);
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "yourApplicationName"), defaultBandwidthMeter);
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(mediaUri);
// Prepare the player with the source.
mExoPlayer.prepare(videoSource);
mExoPlayer.setPlayWhenReady(true);
}
}
/**
* Release ExoPlayer.
*/
private void releasePlayer() {
mExoPlayer.stop();
mExoPlayer.release();
mExoPlayer = null;
}
* toggles the UI to show the correct answer.
*
* #param v The button that was clicked.
*/
#Override
public void onClick(View v) {
// Wait some time so the user can see the correct answer, then go to the next question.
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mExoPlayer.stop();
Intent nextQuestionIntent = new Intent(QuizActivity.this, QuizActivity.class);
nextQuestionIntent.putExtra(REMAINING_SONGS_KEY, mRemainingSampleIDs);
finish();
startActivity(nextQuestionIntent);
}
}, CORRECT_ANSWER_DELAY_MILLIS);
}
/**
* Release the player when the activity is destroyed.
*/
#Override
protected void onDestroy() {
super.onDestroy();
releasePlayer();
mMediaSession.setActive(false);
}
private void initializeMediaSession() {
mMediaSession = new MediaSessionCompat(this, TAG);
mMediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
// Do not let MediaButtons restart the player when the app is not visible.
mMediaSession.setMediaButtonReceiver(null);
mPlaybackStateBuilder = new PlaybackStateCompat.Builder()
// Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player.
.setActions(PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
PlaybackStateCompat.ACTION_PLAY_PAUSE);
mMediaSession.setPlaybackState(mPlaybackStateBuilder.build());
mMediaSession.setCallback(new MediaSessionCompat.Callback() {
#Override
public void onPlay() {
mExoPlayer.setPlayWhenReady(true);
}
#Override
public void onPause() {
mExoPlayer.setPlayWhenReady(false);
}
});
// Start the Media Session since the activity is active.
mMediaSession.setActive(true);
}
public class PlayerListener extends Player.DefaultEventListener {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
//super.onPlayerStateChanged(playWhenReady, playbackState);
if (playbackState == Player.STATE_READY && playWhenReady) {
mPlaybackStateBuilder.setState(STATE_PLAYING, mExoPlayer.getCurrentPosition(), 1f);
} else if (playbackState == Player.STATE_READY) {
mPlaybackStateBuilder.setState(STATE_PAUSED, mExoPlayer.getCurrentPosition(), 1f);
}
mMediaSession.setPlaybackState(mPlaybackStateBuilder.build());
showMediaStyleNotification(mPlaybackStateBuilder.build());
}
}
public static class MediaReceiver extends BroadcastReceiver {
public MediaReceiver() { }
#Override
public void onReceive(final Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
Toast.makeText(context, "Headset unplugged", Toast.LENGTH_SHORT).show();
}
}
}
You should register the Receiver first in the Activity like -
MediaReceiver mr = new MediaReceiver(mPlayerView);
registerReceiver(mr);
then,
private class MediaReceiver extends BroadcastReceiver {
private PlayerView pv;
public MediaReceiver(PlayerView playerView) {
this.pv = playerView;
}
#Override
public void onReceive(final Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
Toast.makeText(context, "Headset unplugged", Toast.LENGTH_SHORT).show();
pv.pause();
}
}
also, don't forget to unregister Receiver in onDestroy() or onPause()
Exoplayer 2.11.0 supports setHandleAudioBecomingNoisy:
SimpleExoPlayer.Builder(this).setHandleAudioBecomingNoisy(true).build()

how to stop audio playing in background in exoplayer

**
Need to implement video stream within a fragment using exoplayer. Streaming works fine but when moved from the fragment activity to other activity or if the screen is rotated, multiple copys of same audio plays in background continuously until the app is killed.how to handle this please help. Thanks in advance.
**
public class VideoFragment extends Fragment {
private SimpleExoPlayerView simpleExoPlayerView;
public SimpleExoPlayer player;
Uri mp4VideoUri;
String TAG ="LOGG";
SharedPrefs sharedPrefs;
TextView notavailable;
String url;
Connection connection;
long media_length;
public VideoFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.video_fragment,container,false);
sharedPrefs = new SharedPrefs(getContext());
connection = new Connection(getContext());
notavailable= (TextView) rootView.findViewById(R.id.videonotavailable);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
simpleExoPlayerView = new SimpleExoPlayerView(getContext());
simpleExoPlayerView = (SimpleExoPlayerView) rootView.findViewById(R.id.player_view);
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
simpleExoPlayerView.setPlayer(player);
DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(getContext(), Util.getUserAgent(getContext(), "exoplayer2example"), bandwidthMeterA);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
url=sharedPrefs.getvideoUrl();
if (url==null || url.equals("")){
simpleExoPlayerView.setVisibility(View.GONE);
notavailable.setVisibility(View.VISIBLE);
}else if (connection.isInternet()){
mp4VideoUri=Uri.parse(sharedPrefs.getvideoUrl());
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,dataSourceFactory,extractorsFactory,null,null);
final LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);
player.prepare(loopingSource);
player.addListener(new ExoPlayer.EventListener() {
#Override
public void onLoadingChanged(boolean isLoading) {
Log.v(TAG,"Listener-onLoadingChanged...");
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.v(TAG,"Listener-onPlayerStateChanged...");
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
Log.v(TAG,"Listener-onTimelineChanged...");
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Log.v(TAG,"Listener-onPlayerError...");
player.stop();
}
#Override
public void onPositionDiscontinuity() {
Log.v("LOG","Listener-onPositionDiscontinuity...");
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
});
player.setPlayWhenReady(true);
}else {
simpleExoPlayerView.setVisibility(View.GONE);
notavailable.setVisibility(View.VISIBLE);
notavailable.setText(getString(R.string.nointernet));
}
return rootView;
}
#Override
public void onPause() {
super.onPause();
if(player != null) {
player.stop();
player.release();
media_length = player.getCurrentPosition();
}
}
#Override
public void onResume() {
super.onResume();
if(player != null) {
player.seekTo(media_length);
player.setPlayWhenReady(true);
}
}
}
In your fragment-holding activity, you need to handle the situation in the onPause method:
#Override
protected void onPause() {
super.onPause();
mPlayerFragment.pause();
}
You can define a method in your fragment to pause playback by passing false to setPlayWhenReady().
public void pausePlayback() {
mExoPlayer.setPlayWhenReady(false); //pauses the playback if it's playing
}
I am facing same issue and problem resolved after implement below code in my existing code
First You need to create global variable
boolean isActivityRunning = false;
Set this value in onCreate() and onResume() of activity to true.
You need to set Player if value isActivityRunning is true
After that you need to release player and set isActivityRunning = false in onPause(), onStop() and onDestroy() that look like
#Override
public void onPause() {
super.onPause();
isActivityRunning = false;
releasePlayer();
}
#Override
public void onStop() {
super.onStop();
isActivityRunning = false;
releasePlayer();
}
#Override
public void onBackPressed() {
super.onBackPressed();
releasePlayer();
}
#Override
protected void onDestroy(){
super.onDestroy();
releasePlayer();
}
and releasePlayer() implementation look like is
SimpleExoPlayer player;
PlayerView playerUI;
private void releasePlayer(){
if(player!=null){
player.release();
player.clearVideoSurface();
playerUI.getPlayer().release();;
player = null;
playerUI =null;
}
}
Where player and player UI is Global variable that need to set null
This solution work well for me.

How I get ExoPlayer to resume a video in my Activity's onStart() method?

I'm using ExoPlayer to play some mp4's from a URL. When the user click's the home button, or anything that causes the app to be removed from the user's view and then comes back to my app (and video activity) I want the video to resume where it left off. I tried implementing this by saving the video position in onStop() and then rebuilding the player and using seekTo() in onStart(). I have a check to see if my current exoplayer is null in onStart(), this check never passes however, so I think this is where the problem lies. How it's coded now my video never resumes. If I leave the app by pressing the home button onStop() gets called and then onStart() will get called when I go back into my app, however the video player remains black and never plays the video. If I remove the null check I get two instances of the video playing whenever I start a video from the main activity because it gets called both in onCreate() and onStart(). Is there a better method for getting the functionality that I want? Any help is appreciated!
public class VideoActivity extends AppCompatActivity {
private SimpleExoPlayer exoPlayer;
private SimpleExoPlayerView simpleExoPlayerView;
private long playerPosition;
private String mp4Url;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.player_activity);
// Get the Intent that started this activity and extract the video url
Intent intent = getIntent();
mp4Url = intent.getStringExtra(MainActivity.VIDEO_URL);
// Create an exoplayer instance and start playing video
buildPlayer(mp4Url);
}
private void buildPlayer(String mp4Url) {
// Create a default TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
// Create the player
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); // no LoadControl?
simpleExoPlayerView = new SimpleExoPlayerView(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
// Set media controller
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
// Bind player to the view
simpleExoPlayerView.setPlayer(exoPlayer);
// Create Uri from video location
// TODO: should this be in some network class? Should I be appending APIKEY here?
Uri mp4Uri = Uri.parse(mp4Url + "?api_key=" + BuildConfig.GIANTBOMB_API_KEY);
Timber.v("Video url with api key: " + mp4Uri.toString());
// Create another bandwidth meter for bandwidth during playback (not strictly necessary)
DefaultBandwidthMeter playbackBandwidthMeter = new DefaultBandwidthMeter();
// DataSourceFactory to produce DataSource instances through which media data is loaded
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "GiantBombForAndroid"),
playbackBandwidthMeter);
// Produces Extractor instances for parsing the media data
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
ExtractorMediaSource.EventListener eventListener = new ExtractorMediaSource.EventListener() {
#Override
public void onLoadError(IOException error) {
Timber.e("Error loading video from source");
}
};
final MediaSource videoSource = new ExtractorMediaSource(mp4Uri,
dataSourceFactory,
extractorsFactory,
mainHandler,
eventListener);
exoPlayer.prepare(videoSource);
exoPlayer.addListener(new ExoPlayer.EventListener() {
#Override
public void onLoadingChanged(boolean isLoading) {
Timber.v("Listener-onLoadingChanged...");
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Timber.v("Listener-onPlayerStateChanged...");
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
Timber.v("Listener-onTimelineChanged...");
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
// TODO: Do I need anything here?
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Timber.v("Listener-onPlayerError...");
exoPlayer.stop();
exoPlayer.prepare(videoSource);
exoPlayer.setPlayWhenReady(true);
}
#Override
public void onPositionDiscontinuity() {
Timber.v("Listener-onPositionDiscontinuity...");
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// TODO: Do I need anything here?
}
});
exoPlayer.setPlayWhenReady(true);
}
#Override
protected void onStart() {
super.onStart();
Timber.v("onStart()...");
if (exoPlayer == null) {
Timber.v("No exoplayer instance, recreating...");
buildPlayer(mp4Url);
exoPlayer.seekTo(playerPosition);
}
}
#Override
protected void onStop(){
super.onStop();
Timber.v("onStop()...");
//TODO: pull player creation code into it's own method so it can be called here as well
playerPosition = exoPlayer.getCurrentPosition();
exoPlayer.release();
}
#Override
protected void onDestroy() {
super.onDestroy();
Timber.v("onDestroy()...");
exoPlayer.release();
}
}
Currently you're calling release in onStop() which will null out all the important pieces of the player, but not the exoPlayer field (and destroy any state that you aren't keeping track of yourself).
There are a few different approaches. But no matter what you do, you'll likely want to keep track of some state yourself. Below I use them as fields, but they could also be placed in onSavedInstanceState(). In onStop() we're saving off two pieces of information and then pulling them out in onStart(). 1) The last position our player was in when pausing and 2) whether we should play when resumed. You can likely move your seekTo call out of the if == null block since you'll probably always want to resume from where you left off.:
#Override
public void onStart() {
// ...
if (exoPlayer == null) {
// init player
}
// Seek to the last position of the player.
exoPlayer.seekTo(mLastPosition);
// Put the player into the last state we were in.
exoPlayer.setPlayWhenReady(mPlayVideoWhenForegrounded);
// ...
}
#Override
public void onStop() {
// ...
// Store off if we were playing so we know if we should start when we're foregrounded again.
mPlayVideoWhenForegrounded = exoPlayer.getPlayWhenReady();
// Store off the last position our player was in before we paused it.
mLastPosition = exoPlayer.getCurrentPosition();
// Pause the player
exoPlayer.setPlayWhenReady(false);
// ...
}
Now the other issue I see with your code sample is that exoPlayer.release() won't null out the field exoPlayer. So you could additionally add the line exoPlayer = null after exoPlayer.release() which should hopefully fix your issue of multiple exoPlayers. You could also move the release() call to onDestroy() but only if you know you're reinstantiating everything correctly.
There is no need to reinit player again. The following code is pretty enough:
#Override
protected void onPause() {
super.onPause();
if (player!=null) {
player.stop();
mLastPosition = player.getCurrentPosition();
}
}
#Override
protected void onResume() {
super.onResume();
//initiatePlayer();
if(mLastPosition!=0 && player!=null){
player.seekTo(mLastPosition);
}
}
Try the following
Get the player position in onPause.
initiate the palyer again in onResume and set seek to the last position of the player
private void initiatePlayer() {
try {
exoPlayer = ExoPlayerFactory.newSimpleInstance(this);
DataSource.Factory dataSourceFactory =
new DefaultDataSourceFactory(this, Util.getUserAgent(this, this.getResources().getString(R.string.app_name)));
DefaultExtractorsFactory extractorsFactory =
new DefaultExtractorsFactory()
.setMp4ExtractorFlags(Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS);
ProgressiveMediaSource progressiveMediaSource =
new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
.createMediaSource(videoUri);
// playerView = new PlayerView(this);
playerView.setPlayer(exoPlayer);
exoPlayer.prepare(progressiveMediaSource);
exoPlayer.setPlayWhenReady(true);
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
ImageView volumeControl = controlView.findViewById(R.id.exo_volume);
mFullScreenIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(ORIENTATION ==Configuration.ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
Timer mRestoreOrientation = new Timer();
mRestoreOrientation.schedule(new TimerTask() {
#Override
public void run() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
}, 2000);
}
});
volumeControl.setOnClickListener(view -> {
float currentvolume = exoPlayer.getVolume();
if (currentvolume > 0f) {
previousVolume = currentvolume;
exoPlayer.setVolume(0f);
volumeControl.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_volume_off_white_24dp));
} else {
exoPlayer.setVolume(previousVolume);
volumeControl.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_volume_up_white_24dp));
}
});
} catch (Exception e) {
e.printStackTrace();
Log.d("MainExcep", e.getMessage());
}
}
#Override
protected void onPause() {
super.onPause();
if (exoPlayer!=null) {
exoPlayer.stop();
mLastPosition = exoPlayer.getCurrentPosition();
}
}
#Override
protected void onResume() {
super.onResume();
initiatePlayer();
if(mLastPosition!=0){
exoPlayer.seekTo(mLastPosition);
}
}
In my case, if i minimize or try to move from the this player video app to another app. The video player app always starting play from 0. I was try and succesfully, the video player app playing video from the last current position when you minimalize or move to another app, and this it.
go to
private void buildPlayer(String mp4Url)
add
player.seekTo(playbackPosition);
and then
#Override
public void onResume() {
super.onResume();
if(playbackPosition!=0 && player!=null){
player.seekTo(playbackPosition);
initializePlayer();
}
}
#Override
public void onPause() {
super.onPause();
player.stop();
if(player != null && player.getPlayWhenReady()) {
player.stop();
playbackPosition = player.getCurrentPosition();
player.setPlayWhenReady(true);
}
}
#Override
public void onStop() {
super.onStop();
player.setPlayWhenReady(false);
player.stop();
player.seekTo(0);
}
And you can try remove the
exoPlayer.setPlayWhenReady(true);
from
private void buildPlayer(String mp4Url)

Categories

Resources