**
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.
Related
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();
}
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.
In my App, I have fragment in which I, alongside with other, play video in ExoPlayer. I set it up as simple as possible and the player itself works flawlessly, even with media session.
But the problem is that on device rotation, the video loads again in background (there seems to be two layers - one standard, functioning normally, loading video and playing it; and second layer in background. I can hear the sound of the video shortly after the activity recreates.
I am stopping and releasing the player and media session, but it didn't help.
MediaFragment.java
public class StepViewFragment extends Fragment implements Player.EventListener{
//vars
public StepViewFragment() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
//attach callbacks for buttons
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_step_view, container, false);
//Bind view ButterKnife
ButterKnife.bind(this, rootView);
//get Step from Bundle
Bundle bundle = this.getArguments();
if (bundle != null) {
step = bundle.getParcelable(AppConstants.STEP_BUNDLE_KEY);
recipe = bundle.getParcelable(AppConstants.RECIPE_BUNDLE_KEY);
}
mainHandler = new Handler();
//...
//setup ui
//...
if (step.videoURL.equals("")) {
mediaCard.setVisibility(View.GONE);
} else {
playVideo();
initMediaSession();
}
return rootView;
}
public void initMediaSession (){
mExoPlayer.addListener(this);
mMediaSession = new MediaSessionCompat(getContext(), TAG);
mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
mMediaSession.setMediaButtonReceiver(null);
mStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE
);
mMediaSession.setPlaybackState(mStateBuilder.build());
mMediaSession.setCallback(new MySessionCallback());
mMediaSession.setActive(true);
}
public void playVideo() {
if (mExoPlayer == null) {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
RenderersFactory renderersFactory = new DefaultRenderersFactory(getContext());
mExoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
mPlayerView.setPlayer(mExoPlayer);
String videoUrl = step.videoURL;
Uri mp4VideoUri = Uri.parse(videoUrl);
String userAgent = Util.getUserAgent(getContext(), "BakingApp");
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getContext(), userAgent);
ExtractorMediaSource.Factory mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory);
mExoPlayer.prepare(mediaSource.createMediaSource(mp4VideoUri));
mPlayerView.hideController();
mExoPlayer.setPlayWhenReady(true);
}
}
public void releasePlayer() {
mExoPlayer.stop();
mExoPlayer.release();
mExoPlayer = null;
mMediaSession.release();
mPlayerView = null;
}
#Override
public void onStop() {
if (mExoPlayer != null) {
releasePlayer();
}
super.onStop();
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (mExoPlayer != null) {
releasePlayer();
}
}
#Override
public void onPause() {
super.onPause();
if (mExoPlayer != null) {
releasePlayer();
}
}
#Override
public void onDetach() {
super.onDetach();
if (mExoPlayer != null) {
releasePlayer();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (mExoPlayer != null){
releasePlayer();
}
}
#Override
public void onTimelineChanged(Timeline timeline, 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) {
if ((playbackState == Player.STATE_READY) && playWhenReady) {
mStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING, mExoPlayer.getCurrentPosition(), 1f);
} else if ((playbackState == Player.STATE_READY)){
mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED, mExoPlayer.getCurrentPosition(), 1f);
}
mMediaSession.setPlaybackState(mStateBuilder.build());
Log.d("HOVNOOOO", "Playback State Changed");
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
private class MySessionCallback extends MediaSessionCompat.Callback {
#Override
public void onPlay() {
mExoPlayer.setPlayWhenReady(true);
}
#Override
public void onPause() {
mExoPlayer.setPlayWhenReady(false);
}
}
Solved...
I was using add() to create the Fragment, so on rotation it added new one.
Using replace instead solved the problem.
I am using ExoPlayer in my activity,What i want is to smoothly play video in portrait and landscape mode.For this purpose what I am doing is in onpause I save the currentPlayerPosition and seek player to that position in onresume but while rotating it face a jerk and video is stopped for a while and played to the saved position.
My code is below please help me how i can smoothly switch the mode portrait and landscape.Thanks
#Override
public void onPause() {
super.onPause();
if (mExoPlayerView != null && mExoPlayerView.getPlayer() != null) {
mResumeWindow = mExoPlayerView.getPlayer().getCurrentWindowIndex();
mResumePosition = Math.max(0, mExoPlayerView.getPlayer().getContentPosition());
mExoPlayerView.getPlayer().release();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (mExoPlayerView.getPlayer() != null)
mExoPlayerView.getPlayer().release();
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_RESUME_WINDOW, mResumeWindow);
outState.putLong(STATE_RESUME_POSITION, mResumePosition);
outState.putBoolean(STATE_PLAYER_FULLSCREEN, mExoPlayerFullscreen);
super.onSaveInstanceState(outState);
}
#Override
protected void onResume() {
super.onResume();
if (mExoPlayerView == null) {
mExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.exoplayer);
videoURL = getIntent().getStringExtra("url");
postID = getIntent().getIntExtra("UserID", 0);
String userAgent = Util.getUserAgent(Vid.this, getApplicationContext().getApplicationInfo().packageName);
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent, null, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(Vid.this, null, httpDataSourceFactory);
Uri daUri = Uri.parse(videoURL);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
if (daUri.toString().startsWith("https://player.vimeo"))
mVideoSource = new HlsMediaSource(daUri, dataSourceFactory, 1, null, null);
else
mVideoSource = new ExtractorMediaSource(daUri, dataSourceFactory, extractorsFactory, null, null);
initExoPlayer();
} else {
resumeExoPlayer();
}
}
private void resumeExoPlayer() {
boolean haveResumePosition = mResumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
hideKeyboard();
hideProgress();
mExoPlayerView.getPlayer().seekTo(mResumeWindow, mResumePosition);
}
}
private void initExoPlayer() {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), trackSelector, loadControl);
mExoPlayerView.setPlayer(player);
boolean haveResumePosition = mResumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
hideKeyboard();
hideProgress();
mExoPlayerView.getPlayer().seekTo(mResumeWindow, mResumePosition);
}
mExoPlayerView.getPlayer().prepare(mVideoSource);
mExoPlayerView.getPlayer().setPlayWhenReady(true);
mExoPlayerView.getPlayer().addListener(new Player.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) {
if (playbackState == ExoPlayer.STATE_ENDED) {
hideProgress();
mExoPlayerView.getPlayer().seekTo(0);
mExoPlayerView.getPlayer().setPlayWhenReady(false);
} else if (playbackState == ExoPlayer.STATE_BUFFERING) {
} else if (playbackState == ExoPlayer.STATE_READY) {
hideProgress();
if (preferenceManager.getLoggedIn()) {
APIGetComment();
}
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
hideProgress();
finish();
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
}
Finally, After wasting 2 days I found it.
Simple add it in the manifest and will work on all android version ?
android:configChanges="orientation|screenSize|layoutDirection"
cheers!
If you want the video to resume on orientation change, you can add this to your manifest android:configChanges="keyboardHidden|orientation|screenSize"
<activity
<activity
android:name=".MainActivity"
android:name=".MainActivity"
android:label="#string/app_name"
android:label="#string/app_name"
+ android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="#style/AppTheme.NoActionBar"
android:theme="#style/AppTheme.NoActionBar"
android:icon="#mipmap/ic_launcher_2">
android:icon="#mipmap/ic_launcher_2">
<intent-filter>
<intent-filter>
No need of any additional coding, simply add this line
android:configChanges="keyboardHidden|orientation|screenSize"
in your AndroidManifest.xml's activity section.
I also wasted quite a lot time in this. Take a look at it EXO PLAYER 2.11.2
implementation 'com.google.android.exoplayer:exoplayer:2.11.2'
STEP - 1 Make an activity in which string url is passed as intent.
public class VideoPlayerActivity extends Activity {
public static final String sURL_KEY = "STREAMING_URL_KEY";
public static final String sTOAST_TEXT = "Unable to stream, no media found";
static final String LOADING = "PLAYER_LOADING";
static final String STOPPED = "PLAYER_STOPPED";
static final String PAUSED = "PLAYER_PAUSED";
static final String PLAYING = "PLAYER_PLAYING";
static final String IDLE = "PLAYER_IDLE";
private static final String TAG = "StreamMediaActivity";
int orientation;
private Uri streamUrl;
private SimpleExoPlayer mPlayer;
private PlayerView playerView;
private ProgressBar progressBar;
private String mPlayerStatus;
private long mPlaybackPosition = 0L;
private boolean mIsPlayWhenReady = true;
private int mCurrentWindow = 0;
private Display display;
private String STATE_RESUME_WINDOW = "resumeWindow";
private String STATE_RESUME_POSITION = "resumePosition";
private String STATE_PLAYER_FULLSCREEN = "playerFullscreen";
private boolean mExoPlayerFullscreen = false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fullScreen();
display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
orientation = display.getRotation();
setContentView(R.layout.activity_video_player);
playerView = findViewById(R.id.player_view);
progressBar = findViewById(R.id.progressBar_player);
// Pass a string uri to this class
String urlString = getIntent().getStringExtra(sURL_KEY);
if (urlString != null) {
streamUrl = Uri.parse(urlString);
} else {
Toast.makeText(this, sTOAST_TEXT, Toast.LENGTH_LONG).show();
finish();
}
}
#Override
protected void onStart() {
super.onStart();
initPlayer();
}
#Override
protected void onResume() {
super.onResume();
if (mPlaybackPosition != 0L && mPlayer != null) {
mPlayer.seekTo(mCurrentWindow, mPlaybackPosition);
}
}
#Override
protected void onStop() {
super.onStop();
}
#Override protected void onPause() {
super.onPause();
releasePlayer();
}
private void initPlayer() {
// ESTABLISH THE DATA SOURCE FROM URL
// here i'm playing local video file that's
// why using the DefaultDataSourceFactory but you
//may use DefaultHttpDataSourceFactory to stream
//online videos
DataSource.Factory dataSourceFactory =
new DefaultDataSourceFactory(this, Util.getUserAgent(this, getApplicationInfo().name));
MediaSource mediaSource =
new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(
streamUrl);
// CREATE A NEW INSTANCE OF EXO PLAYER
if (mPlayer == null) {
mPlayer = new SimpleExoPlayer.Builder(this, new DefaultRenderersFactory(this)).build();
playerView.setPlayer(mPlayer);
progressBar.setVisibility(View.VISIBLE);
}
mPlayer.setPlayWhenReady(mIsPlayWhenReady);
mPlayer.seekTo(mCurrentWindow, mPlaybackPosition);
// PREPARE MEDIA PLAYER
mPlayer.prepare(mediaSource, true, false);
mPlayer.addListener(new Player.EventListener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_BUFFERING:
mPlayerStatus = LOADING;
runOnUiThread(() -> progressBar.setVisibility(View.VISIBLE));
break;
case Player.STATE_ENDED:
mPlayerStatus = STOPPED;
break;
case Player.STATE_READY:
mPlayerStatus = (playWhenReady) ? PLAYING : PAUSED;
runOnUiThread(() -> progressBar.setVisibility(View.INVISIBLE));
break;
default:
mPlayerStatus = IDLE;
break;
}
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Toast.makeText(VideoPlayerActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
finish();
}
});
}
#Override protected void onSaveInstanceState(Bundle outState) {
mExoPlayerFullscreen = !mExoPlayerFullscreen;
super.onSaveInstanceState(outState);
outState.putInt(STATE_RESUME_WINDOW, mCurrentWindow);
outState.putLong(STATE_RESUME_POSITION, mPlaybackPosition);
outState.putBoolean(STATE_PLAYER_FULLSCREEN, mExoPlayerFullscreen);
super.onSaveInstanceState(outState);
}
public void fullScreen() {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
private void releasePlayer() {
if (mPlayer != null) {
mPlayer.stop();
mPlaybackPosition = mPlayer.getCurrentPosition();
mCurrentWindow = mPlayer.getCurrentWindowIndex();
mIsPlayWhenReady = mPlayer.getPlayWhenReady();
playerView.setPlayer(null);
mPlayer.release();
mPlayer = null;
}
}
}
Step 2 : Make the XML layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black">
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
android:keepScreenOn="true"
app:use_controller="true"
app:resize_mode="fit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/progressBar_player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
STEP 3: start VideoPlayerActivity using intent from another activity
Intent streamVideoIntent = new Intent(context, VideoPlayerActivity.class);
streamVideoIntent.putExtra(sURL_KEY, stringUrl);
context.startActivity(streamVideoIntent);
STEP 4 : Lastly add activity to manifest
<activity android:name=".ui.videoplayer.VideoPlayerActivity"
android:configChanges="orientation|screenSize|layoutDirection"
/>
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.