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();
}
Related
If we open our app the news fragment is loaded and the news automatically starts to play. We are using Exoplayer for playing the news. Notification is created by Exoplayer via PlayerNotificationManager. The problem is that the play pause button doesn't follow the notification. We have implemented eventbus & it only changes the drawable. So, if we click on pause button on the notification, the button on fragment is seen as paused but when we click on it works as a pause button (instead of working as a play button).
What we intend to do is: If the notification says paused the button on fragment will be paused & then if we click on it the content will start to play.
Codes:
NewsReaderFragment.java
public static NewsReaderFragment newInstance() {
return new NewsReaderFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_news_reader, container, false);
bPlay = rootView.findViewById(R.id.button_play);
unbinder = ButterKnife.bind(this, rootView);
NetworkInfoUtility networkInfoUtility = new NetworkInfoUtility();
boolean net = networkInfoUtility.isNetWorkAvailableNow(getContext());
if (!net) {
Toast.makeText(getContext(), CHECKNET, Toast.LENGTH_LONG).show();
}
exoHelper = new ExoHelper(getContext(), new Player.EventListener() {
#Override
public void onPlayerError(ExoPlaybackException error) {
Crashlytics.logException(error);
Toast.makeText(getContext(), rootView.getContext().getString(R.string.server_off), Toast.LENGTH_LONG).show();
exoHelper.ToggleButton(false);
}
}, bPlay, "NewsReader");
isPlaying = true;
setButton();
exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
return rootView;
}
private void setButton() {
bPlay.setOnClickListener(view -> {
if (!isPlaying) {
exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
} else {
exoHelper.stopExo();
}
isPlaying = !isPlaying;
});
}
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ButtonEvent event)
{
exoHelper.ToggleButton(event.isState());
}
Exophelper.java
public void stopExo() {
if (exoPlayer != null) { //if exo is running
Log.d(TAG, "Stopping exo....");
exoPlayer.stop();
//playerNotificationManager.setPlayer(null);
customPlayerNotificationManager.setPlayer(null);
exoPlayer.release();
exoPlayer = null;
ToggleButton(false);
} else {
Log.d(TAG, "Can't stop because No exoplayer is running");
}
}
public void startExo(String newUrl) {
if (newUrl == null || newUrl.isEmpty()) {
Log.d(TAG, "startExo: empty url");
Toast.makeText(context, R.string.server_off, Toast.LENGTH_SHORT).show();
ToggleButton(false); // show pause button
return;
}
if (exoPlayer != null) {
Log.d(TAG, "startExo: Exo is already running now");
return;
}
iceURL = newUrl;
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
TrackSelection.Factory trackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector defaultTrackSelector =
new DefaultTrackSelector(trackSelectionFactory);
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
context,
Util.getUserAgent(context, context.getApplicationInfo().name),
defaultBandwidthMeter);
MediaSource mediaSource = new ExtractorMediaSource(
Uri.parse(iceURL),
dataSourceFactory,
extractorsFactory,
new Handler(), error -> {
});
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, defaultTrackSelector);
if (eventListener != null) {
exoPlayer.addListener(eventListener);
}
exoPlayer.prepare(mediaSource);
exoPlayer.setPlayWhenReady(true);
//EventStatus(true);
ToggleButton(true);
//setPlayerNotificationManager(exoPlayer);
createCustomPlayerNotificationManger(exoPlayer);
}
public void ToggleButton(boolean state) {
if (state) {
Drawable img = button.getContext().getResources().getDrawable(R.drawable.play_button);
button.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
button.setText(R.string.now_playing);
} else {
Drawable img1 = button.getContext().getResources().getDrawable(R.drawable.pause_button);
button.setCompoundDrawablesWithIntrinsicBounds(img1, null, null, null);
button.setText(R.string.server_off);
}
}
PlayerNotificationManager.java
It's a big file, so we are attaching only the receiver where we use eventbus:
public class NotificationBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Player player = PlayerNotificationManager.this.player;
if (player == null
|| !isNotificationStarted
|| intent.getIntExtra(EXTRA_INSTANCE_ID, instanceId) != instanceId) {
return;
}
String action = intent.getAction();
if (ACTION_PLAY.equals(action)) {
if (player.getPlaybackState() == Player.STATE_IDLE) {
if (playbackPreparer != null) {
playbackPreparer.preparePlayback();
}
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
}
controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true);
EventBus.getDefault().post(new ButtonEvent(true));
Log.d(TAG, "ButtonEvent: True");
} else if (ACTION_PAUSE.equals(action)) {
controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false);
if (player.getPlaybackState() == Player.STATE_READY)
{
EventBus.getDefault().post(new ButtonEvent(false));
Log.d(TAG, "ButtonEvent: False");
}
} else if (ACTION_STOP.equals(action)) {
controlDispatcher.dispatchStop(player, /* reset= */ true);
} else if (ACTION_DISMISS.equals(action)) {
stopNotification(/* dismissedByUser= */ true);
} else if (action != null
&& customActionReceiver != null
&& customActions.containsKey(action)) {
customActionReceiver.onCustomAction(player, action, intent);
}
}
}
ButtonEvent.java
public class ButtonEvent {
public boolean state;
public ButtonEvent(boolean state) {
this.state = state;
}
public boolean isState() {
return state;
}
public void setState(boolean state) {
this.state = state;
}
}
Is it correct that isPlaying is true in this scenario, executing a second pause?
private void setButton() {
bPlay.setOnClickListener(view -> {
if (!isPlaying) {
exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
} else {
exoHelper.stopExo();
}
isPlaying = !isPlaying;
});
}
Is there a reason why the state of whether it is playing it tied to the Fragment and not ExoHelper?
Maybe this can be remedied easily by re-assigning isPlaying with exoplayers event listener...
player.addListener(eventListener);
...
#Override
public void onIsPlayingChanged(boolean isPlaying) {
if (isPlaying) {
// player is playing
} else {
// player is paused
}
}
UPDATE
Or query exoplayer directly for state:
private void setButton() {
bPlay.setOnClickListener(view -> {
if (!isPlaying()) {
exoHelper.startExo(rootView.getContext().getString(R.string.bbc_news));
} else {
exoHelper.stopExo();
}
});
}
// this method might belong in ExoHelper?
private boolean isPlaying() {
return player.getPlaybackState() == Player.STATE_READY && player.getPlayWhenReady();
}
Further reading https://exoplayer.dev/listening-to-player-events.html
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.
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.
**
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.