Implementing audio app notification in Android - java

The purpose of application is to play some radio stations via url streaming using exoplayer. The problem encountered is that when the app is running and the notification starts there are 2 different streams playing one by my button press from the radio UI and one by the notification.
My question is how can I make it so when I press a button on the UI it changes the the stream on the notification player as well.
P.S. I have tried importing one player however that proved from mainactivity.java by calling it a static however that causes a memory leak and the stream stop in the foreground service.
I used the notificationPlayerManager(exoplayer) from here: https://www.youtube.com/watch?v=svdq1BWl4r8
Main Activity class:
package-----------etc
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import org.atsevdev.radioromania.MyServices.*;
import android.view.View;
public class MainActivity extends AppCompatActivity {
public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
//initialising variables
public static final String DigiFm = "http://edge76.rdsnet.ro:84/digifm/digifm.mp3";
public static final String radio_zu = "http://live.romanticfm.ro:9123/radiozu.mp3";
public static final String Radio_popular = "http://mp3.radiopopular.ro:7777/;stream.mp3";
public static final String Eur_fm = "http://89.37.58.103:8000/europafm_mp3_64k";
public static final String radio_rom_acc = "http://stream2.srr.ro:8000/;stream/1";
public static final String PROFMurl = "http://edge126.rdsnet.ro:84/profm/profm.mp3";
public static final String radiobuchuresti = "http://89.238.227.6:8032/\n" +
"Title1=Bucuresti FM\n" +
"Length1=-1\n" +
"Version=2";
public static final String impactfm = "http://89.39.189.159:8000/";
private PlayerView playerView;
public SimpleExoPlayer player;
public boolean clickCheck = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playerView=findViewById(R.id.playview);//playview id xml into private variable
Intent playService = new Intent(this, MyServices.class);
Util.startForegroundService(this, playService);
}
#Override
protected void onStart(){
super.onStart();
player = ExoPlayerFactory.newSimpleInstance(this,
new DefaultTrackSelector());//instantiating new player instances
playerView.setPlayer(player);//xml player to view
//creating datasource
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "RadioRomania"));
//extracting stream url
final ExtractorMediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(PROFMurl));
final ExtractorMediaSource mediaSource0 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(radiobuchuresti));
final ExtractorMediaSource mediaSource1 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(impactfm));
final ExtractorMediaSource mediaSource2 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(radio_rom_acc));
final ExtractorMediaSource mediaSource3 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(Eur_fm));
final ExtractorMediaSource mediaSource4 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(Radio_popular));
final ExtractorMediaSource mediaSource5 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(radio_zu));
final ExtractorMediaSource mediaSource6 = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(DigiFm));
//start video player
FloatingActionButton stop = (FloatingActionButton) findViewById(R.id.stopPLAY);
FloatingActionButton bt = (FloatingActionButton) findViewById(R.id.profm);
FloatingActionButton bt0 = (FloatingActionButton) findViewById(R.id.rad_buc);//buchuresti
FloatingActionButton bt1 = (FloatingActionButton) findViewById(R.id.impactfm);//impact
FloatingActionButton bt2 = (FloatingActionButton) findViewById(R.id.radio_ro_acc);
FloatingActionButton bt3 = (FloatingActionButton) findViewById(R.id.europafm);
FloatingActionButton bt4 = (FloatingActionButton) findViewById(R.id.radpopular);
FloatingActionButton bt5 = (FloatingActionButton) findViewById(R.id.Radiozuu);
FloatingActionButton bt6 = (FloatingActionButton) findViewById(R.id.DigiFm);
//using onClick methods to choose radio station
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //ini profm
clickCheck = true;
player.prepare(mediaSource);
player.setPlayWhenReady(clickCheck);
}
});
bt0.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //ini impact
clickCheck = true;
player.prepare(mediaSource0);
player.setPlayWhenReady(clickCheck);
}
});
bt1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){ //ini radio ro acc
clickCheck = true;
player.prepare(mediaSource1);
player.setPlayWhenReady(clickCheck);
}
});
bt2.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){ //ini radio ro acc
clickCheck = true;
player.prepare(mediaSource2);
player.setPlayWhenReady(clickCheck);
}
});
bt3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //ini profm
clickCheck = true;
player.prepare(mediaSource3);
player.setPlayWhenReady(clickCheck);
}
});
bt4.setOnClickListener(new View.OnClickListener() {//ini radio popular
#Override
public void onClick(View v) {
player.prepare(mediaSource4);
}
});
bt5.setOnClickListener(new View.OnClickListener() {//ini radio popular
#Override
public void onClick(View v) {
clickCheck = true;
player.prepare(mediaSource5);
player.setPlayWhenReady(clickCheck);
}
});
bt6.setOnClickListener(new View.OnClickListener() {//ini radio popular
#Override
public void onClick(View v) {
}
});
//stop stream here
stop.setOnClickListener(new View.OnClickListener() {//ini radio popular
#Override
public void onClick(View v) {
player.setPlayWhenReady(false);
}
});
}
#Override
protected void onStop(){
super.onStop();
playerView.setPlayer(null);
player.release();
player = null;
}
service class:
package ---etc
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.IBinder;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import org.atsevdev.radioromania.MainActivity.*;
public class MyServices extends Service {
private SimpleExoPlayer player1;
private PlayerNotificationManager playerNotificationManager;
public boolean clickCheck = false;
//importing urls from main
public String DigiFm = MainActivity.DigiFm;
public String radioZU = MainActivity.radio_zu;
public String europaFM = MainActivity.Eur_fm;
public String radio_acc_ro = MainActivity.radio_rom_acc;
public String radio_bucuresti = MainActivity.radiobuchuresti;
public String impactFM = MainActivity.impactfm;
public String radiopopular = MainActivity.Radio_popular;
public String PROfm = MainActivity.PROFMurl;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(){
super.onCreate();
final Context context = this;
player1 = ExoPlayerFactory.newSimpleInstance(context, new DefaultTrackSelector());
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
context, Util.getUserAgent(context, "RadioRomania"));
//////////////////////Media Sources/////////////////////////////////
final MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(DigiFm));
final MediaSource mediaSource0 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(radioZU));
final MediaSource mediaSource1 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(radiopopular));
final MediaSource mediaSource2 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(europaFM));
final MediaSource mediaSource3 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(radio_acc_ro));
final MediaSource mediaSource4 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(PROfm));
final MediaSource mediaSource5 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(radio_bucuresti));
final MediaSource mediaSource6 = new ExtractorMediaSource.Factory(dataSourceFactory).
createMediaSource(Uri.parse(impactFM));
player1.prepare(mediaSource);
player1.prepare(mediaSource0);
player1.prepare(mediaSource1);
player1.prepare(mediaSource2);
player1.prepare(mediaSource3);
player1.prepare(mediaSource4);
player1.prepare(mediaSource5);
player1.prepare(mediaSource6);
player1.setPlayWhenReady(clickCheck);
////////////////////////////////////////////////////////////////////////////////
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
context, "Channel ID", R.string.app_name, 0,
new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public String getCurrentContentTitle(Player player) {
return null;
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
Intent intent = new Intent(context, MainActivity.class);
return PendingIntent.getActivity(context, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
}
#Nullable
#Override
public String getCurrentContentText(Player player) {
return null;
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return null;
}
}
);
playerNotificationManager.setNotificationListener(new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationStarted(int notificationId, Notification notification) {
startForeground(0, notification);
clickCheck = true;
}
#Override
public void onNotificationCancelled(int notificationId) {
stopSelf();
clickCheck = false;
}
});
playerNotificationManager.setPlayer(player1);
}
public int onStardCommand(Intent intent, int flats, int stardId){
return START_STICKY;
}
#Override
public void onDestroy(){
playerNotificationManager.setPlayer(null);
player1.release();
player1 = null;
}
}

After some research I have found an answer. For anyone else looking bind the main activity to the service.
In that process I have used this method to bind the player from the service:
public SimpleExoPlayer getPlayer1()
{
return player1;
}
Then call it in your main:
player = myServices.player1;

Related

ClassCastException: com.nambimobile.widgets.efab.ExpandableFabLayout cannot be cast to Activity onCreate

So I'm adding an expandable fab, but I'm having this error and I don't understand why...
this is the exact error in log:
ava.lang.ClassCastException: com.nambimobile.widgets.efab.ExpandableFabLayout cannot be cast to com.nambimobile.widgets.efab.ExpandableFab
at CategoryActivity.onCreate(CategoryActivity.java:56)
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
public class CategoryActivity extends AppCompatActivity implements CategoryAdapter.onCategoryClickListener {
public static final String CATEGORY_NAME = "category_name";
private NoteViewModel noteViewModel;
private CategoryAdapter adapter;
private RecyclerView recyclerView;
private List<FolderWithNotes> folderWithNotes;
private Note note;
private Folder folder;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
noteViewModel = new ViewModelProvider.AndroidViewModelFactory(this.getApplication()).create(NoteViewModel.class);
recyclerView = findViewById(R.id.category_recyclerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
noteViewModel.getFolderWithNotes().observe(this, folderWithNotes -> {
});
ExpandableFab exFab = findViewById(R.id.exFab);
exFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case (R.id.exfab_add_category):
Intent intent = new Intent(CategoryActivity.this, AddCategoryActivity.class);
startActivity(intent);
case (R.id.exfab_delete_category):
default:
break;
}
}
});
ActivityResultLauncher<Intent> launcher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> {
if(result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
String category = data.getStringExtra(AddCategoryActivity.CATEGORY_REPLY);
String notes = data.getStringExtra(AddNoteActivity.NOTE_REPLY);
Folder folder = new Folder(note.getFolder_name());
noteViewModel.insert(folder, note);
}
});
}
#Override
protected void onResume() {
super.onResume();
adapter = new CategoryAdapter(folderWithNotes, this, this);
recyclerView.setAdapter(adapter);
}
#Override
public void onCategoryClick(int position) {
// code to transfer to AddNoteActivity (where the note list is) by clicking the category folder
noteViewModel.getFolderWithNotes().observe(this, folderWithNotes -> {
Intent intent = new Intent(CategoryActivity.this, NotesActivity.class);
intent.putExtra(CATEGORY_NAME, folderWithNotes.get(position).getFolder().getFolderName());
});
}
public void addCategoryClicked(View view) {
EditText editCategory = findViewById(R.id.et_add_category);
String categoryTitle = editCategory.getText().toString().trim();
Intent intent = new Intent(CategoryActivity.this, AddCategoryActivity.class);
}
public void deleteCategoryClicked(View view) {
}
// #Override
// public void addCategoryClicked(int position) {
//
// }
//
}

Runnable not works

I have problem with Runnable. It don't want to works, and i don't know what is the problem, because it is works in my other app... Can somebody help me?
Just example, there are "healt" with deafult value=5, for the test i made a button, when i click button, healt value -1... and i want start Runnable when health<5... and add +1 to health.... for the test i setted the Runnable 1 secunds
Here is the code:
MainActivity.java
package com.mygame.test;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import static com.mygame.test.variables.coin;
import static com.mygame.test.variables.health;
public class Main2Activity extends AppCompatActivity {
public static final String PREFS_NAME_MAIN = "mainpref";
TextView coinText, healthText, textView;
Button button3;
private final Context app = this;
private final Handler update = new Handler();
private final Runnable updateHealth = new Runnable()
{
public void run()
{
if (variables.run)
{
healthText.setText(""+health);
update.postDelayed(updateHealth, 500);
}
else if (!variables.run) update.removeCallbacksAndMessages(null);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main2);
coinText = findViewById(R.id.coinText);
healthText = findViewById(R.id.healthText);
healthText.setText(String.valueOf(health));
button3 = findViewById(R.id.button3);
textView = findViewById(R.id.textView);
Button closeButton = findViewById(R.id.closeButton);
closeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//finishAffinity();
startActivity(new Intent(Main2Activity.this, ExitActivity.class));
}
});
Button coinsplusButton = findViewById(R.id.coinsplusButton);
coinsplusButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//finishAffinity();
startActivity(new Intent(Main2Activity.this, StoreActivity.class));
}
});
Button level1Button = findViewById(R.id.level1Button);
level1Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//finishAffinity();
startActivity(new Intent(Main2Activity.this, Level1Activity.class));
}
});
}
public void buttontest(View button3)
{
if (health > 0) {
health = health-1;
healthText.setText(""+health);
}
variables.run = true;
Intent activeClick = new Intent(this, ClickService.class);
this.startService(activeClick);
update.post(updateHealth);
save();
}
#Override
protected void onStart()
{
super.onStart();
load();
textupgrade();
if (!variables.run)
{
variables.run = true;
Intent activeClick = new Intent(this, ClickService.class);
this.startService(activeClick);
}
}
protected void onResume()
{
super.onResume();
load();
textupgrade();
update.post(updateHealth);
}
private void load()
{
SharedPreferences varReader = app.getSharedPreferences(PREFS_NAME_MAIN, MODE_PRIVATE);
variables.run = varReader.getBoolean("run", false);
coin = varReader.getInt("coin", 0);
health = varReader.getInt("health", 5);
}
private void save()
{
SharedPreferences.Editor varReader = app.getSharedPreferences(PREFS_NAME_MAIN, 0).edit();
varReader.putBoolean("run", variables.run);
varReader.putInt("coin", coin);
varReader.putInt("health", health);
varReader.apply();
}
private void textupgrade(){
coinText.setText(""+coin);
healthText.setText(""+health);
}
}
ClickService.java
package com.mygame.test;
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
public class ClickService extends IntentService
{
private final Handler handler = new Handler();
private final Runnable addHealth = new Runnable()
{
public void run()
{
variables.health++;
if (!variables.run) handler.removeCallbacksAndMessages(null);
else if (variables.run) handler.postDelayed(addHealth, 1000);
}
};
public ClickService()
{
super("ClickService");
}
#Override
protected void onHandleIntent(Intent activeClick)
{
handler.postDelayed(addHealth, 500);
}
}
variables.java
package com.mygame.test;
public class variables {
static int coin;
static int health;
static boolean run;
}
Oh, i fixed it :D ClickService was not registered in AndroidManifest
<service
android:name=".ClickService"
android:exported="false" />

Losing state of the activity when navigating from notification to activity

I have an activity named Player Activity in which I am streaming music with the help of MediaPlayer API. Whenever my activity is created a notification is displayed which has some basic control of the music player.
So when I tap on my notification it jumps back to the Player Activity, but the state of the activity is lost.
Before tapping on notification :
After tapping on notification :
Here is the code of my notification's Pending Intent
Intent notifyIntent = new Intent(context, PlayerActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
notifyIntent.setAction("android.intent.action.MAIN");
notifyIntent.addCategory("android.intent.category.LAUNCHER");
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Here is the code for PlayerActivity.java :
package com.example.user.musicplayer;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.concurrent.TimeUnit;
import de.hdodenhof.circleimageview.CircleImageView;
public class PlayerActivity extends AppCompatActivity implements MediaPlayer.OnBufferingUpdateListener,MediaPlayer.OnCompletionListener{
private static Button btn_play_pause;
private Button btnToggleRepeat;
private Button btnStop;
private SeekBar seekBar;
private TextView textView;
public static MediaPlayer mediaPlayer;
private int mediaFileLength;
private int realtimeLength;
private String musicUrl;
private String imageUrl;
final Handler handler = new Handler();
private boolean isRepeat;
private CircleImageView musicImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
Log.d("TAG", "onCreate");
NotificationGenerator.customBigNotification(getApplicationContext());
musicUrl = getIntent().getStringExtra("musicUrl");
imageUrl = getIntent().getStringExtra("imageUrl");
seekBar = (SeekBar)findViewById(R.id.seekbar);
seekBar.setMax(99); // 100% (0~99)
seekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(mediaPlayer.isPlaying())
{
SeekBar seekBar = (SeekBar)v;
int playPosition = (mediaFileLength/100)*seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
}
return false;
}
});
textView = (TextView)findViewById(R.id.txtTime);
btnToggleRepeat = findViewById(R.id.btnRepeat);
btnStop = findViewById(R.id.btnStop);
musicImage = findViewById(R.id.musicImgView);
Picasso.get().load(imageUrl).placeholder(R.drawable.music).error(R.drawable.music).into(musicImage);
btn_play_pause = (Button) findViewById(R.id.btnTogglePlay);
btn_play_pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog mDialog = new ProgressDialog(PlayerActivity.this);
AsyncTask<String,String,String> mp3Play = new AsyncTask<String, String, String>() {
#Override
protected void onPreExecute() {
mDialog.setMessage("Please wait");
mDialog.show();
}
#Override
protected String doInBackground(String... params) {
try{
mediaPlayer.setDataSource(params[0]);
mediaPlayer.prepare();
}
catch (Exception ex)
{
}
return "";
}
#Override
protected void onPostExecute(String s) {
mediaFileLength = mediaPlayer.getDuration();
realtimeLength = mediaFileLength;
if(!mediaPlayer.isPlaying())
{
playMusic();
}
else
{
pauseMusic();
}
updateSeekBar();
mDialog.dismiss();
}
};
mp3Play.execute(musicUrl); // direct link mp3 file
}
});
btnToggleRepeat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isRepeat){
isRepeat = false;
mediaPlayer.setLooping(false);
btnToggleRepeat.setText("Repeat");
}
else{
isRepeat = true;
mediaPlayer.setLooping(true);
btnToggleRepeat.setText("Single");
}
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
mediaPlayer.pause();
mediaPlayer.stop();
}
catch (Exception e){
Toast.makeText(PlayerActivity.this, "Opps! sorry something bad happened", Toast.LENGTH_SHORT).show();
}
}
});
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
public void pauseMusic() {
mediaPlayer.pause();
btn_play_pause.setText("Play");
}
public void playMusic() {
mediaPlayer.start();
btn_play_pause.setText("Pause");
}
private void updateSeekBar() {
seekBar.setProgress((int)(((float)mediaPlayer.getCurrentPosition() / mediaFileLength)*100));
if(mediaPlayer.isPlaying())
{
Runnable updater = new Runnable() {
#Override
public void run() {
updateSeekBar();
realtimeLength-=1000; // declare 1 second
textView.setText(String.format("%d:%d",TimeUnit.MILLISECONDS.toMinutes(realtimeLength),
TimeUnit.MILLISECONDS.toSeconds(realtimeLength) -
TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes(realtimeLength))));
}
};
handler.postDelayed(updater,1000); // 1 second
}
}
#Override
protected void onResume() {
super.onResume();
Log.d("TAG", "onResume");
}
#Override
protected void onStart() {
super.onStart();
Log.d("TAG", "onStart");
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
seekBar.setSecondaryProgress(percent);
}
#Override
public void onCompletion(MediaPlayer mp) {
if(!mediaPlayer.isLooping())
btn_play_pause.setText("Play");
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onPause() {
super.onPause();
}
public static class DownloadCancelReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("notificationPlayer","Received Cancelled Event");
}
}
}
Thanks in advance. Pardon me if the explanation is not clear, because if i might have right words to explain it, I would have googled it.
Add this to your PlayerActivity activity in manifest :
android:launchMode="singleTask"
And use these flags in the intent for pendingintent :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

Error of Glide library: You cannot start a load from a destroyed Activity

I'm using Recycle Adapter class and using this to populate the fragments with blog image and description. But when I close the BlogActivity and move to Next Activity then sometimes suddenly app get crashed with error of
java.lang.IllegalArgumentException:You cannot start a load for a destryoed activity at com.bumptech.glide.manager.RequestManagerRetriever.asseertNotDestroyed(RequestManagerRetriver.java:312)
My Recycle adapter classs code is
package com.nepalpolice.cdp;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FieldValue;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.hdodenhof.circleimageview.CircleImageView;
import static com.android.volley.VolleyLog.TAG;
import static com.nepalpolice.cdp.webfaq.isNetworkStatusAvialable;
public class BlogRecyclerAdapter extends RecyclerView.Adapter<BlogRecyclerAdapter.ViewHolder> {
public List<BlogPost> blog_list;
public Context context;
private FirebaseFirestore firebaseFirestore;
private FirebaseAuth firebaseAuth;
private PopupWindow popWindow;
public BlogRecyclerAdapter(List<BlogPost> blog_list){
this.blog_list = blog_list;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.blog_list_item, parent, false);
context = parent.getContext();
firebaseFirestore = FirebaseFirestore.getInstance();
firebaseAuth = FirebaseAuth.getInstance();
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.setIsRecyclable(false);
final String blogPostId = blog_list.get(position).BlogPostId;
final String currentUserId = firebaseAuth.getCurrentUser().getUid();
String desc_data = blog_list.get(position).getDesc();
holder.setDescText(desc_data);
String image_url = blog_list.get(position).getImage_url();
String thumbUri = blog_list.get(position).getImage_thumb();
holder.setBlogImage(image_url, thumbUri);
String user_id = blog_list.get(position).getUser_id();
//User Data will be retrieved here...
firebaseFirestore.collection("Users").document(user_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()){
String userName = task.getResult().getString("name");
String userImage = task.getResult().getString("image");
holder.setUserData(userName, userImage);
} else {
//Firebase Exception
}
}
});
try {
long millisecond = blog_list.get(position).getTimestamp().getTime();
String dateString = DateFormat.format("MM/dd/yyyy", new Date(millisecond)).toString();
holder.setTime(dateString);
} catch (Exception e) {
Toast.makeText(context, "Exception : " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
//Get Likes Count
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").addSnapshotListener(((Main2Activity) context),new EventListener<QuerySnapshot>() {
#Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
if (e!=null) {
Log.w(TAG, "listening failed",e);
return;
}
if(!documentSnapshots.isEmpty()){
int count = documentSnapshots.size();
holder.updateLikesCount(count);
} else {
holder.updateLikesCount(0);
}
}
});
//Get Likes
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).addSnapshotListener(((Main2Activity) context),new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
if (e!=null) {
Log.w(TAG, "listening failed",e);
return;
}
if (documentSnapshot.exists()){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.blogLikeBtn.setImageDrawable(context.getDrawable(R.mipmap.action_like_accent));
}
else {
holder.blogLikeBtn.setImageDrawable(context.getResources().getDrawable(R.mipmap.action_like_accent));
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.blogLikeBtn.setImageDrawable(context.getDrawable(R.mipmap.action_like_gray));
}else{
holder.blogLikeBtn.setImageDrawable(context.getResources().getDrawable(R.mipmap.action_like_gray));
}
}
}
});
//Likes Feature
holder.blogLikeBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if(!task.getResult().exists()){
Map<String, Object> likesMap = new HashMap<>();
likesMap.put("timestamp", FieldValue.serverTimestamp());
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).set(likesMap);
} else {
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).delete();
}
}
});
}
});
holder.blogCommentBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent commentIntent = new Intent(context, CommentsActivity.class);
context.startActivity(commentIntent);
}
});
}
#Override
public int getItemCount() {
return blog_list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private View mView;
private TextView descView;
private ImageView blogImageView;
private TextView blogDate;
private TextView blogUserName;
private CircleImageView blogUserImage;
private ImageView blogLikeBtn;
private TextView blogLikeCount;
private ImageView blogCommentBtn;
public ViewHolder(View itemView) {
super(itemView);
mView = itemView;
blogLikeBtn = mView.findViewById(R.id.blog_like_btn);
blogCommentBtn = mView.findViewById(R.id.blog_comment_icon);
}
public void setDescText(String descText){
descView = mView.findViewById(R.id.blog_desc);
descView.setText(descText);
}
public void setBlogImage(String downloadUri, String thumbUri){
blogImageView = mView.findViewById(R.id.blog_image);
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.image_placeholder);
Glide.with(context).applyDefaultRequestOptions(requestOptions).load(downloadUri).thumbnail(
Glide.with(context).load(thumbUri)
).into(blogImageView);
}
public void setTime(String date) {
blogDate = mView.findViewById(R.id.blog_date);
blogDate.setText(date);
}
public void setUserData(String name, String image){
blogUserImage = mView.findViewById(R.id.blog_user_image);
blogUserName = mView.findViewById(R.id.blog_user_name);
blogUserName.setText(name);
RequestOptions placeholderOption = new RequestOptions();
placeholderOption.placeholder(R.drawable.profile_placeholder);
Glide.with(context).applyDefaultRequestOptions(placeholderOption).load(image).into(blogUserImage);
}
public void updateLikesCount(int count){
blogLikeCount = mView.findViewById(R.id.blog_like_count);
blogLikeCount.setText(count + " Likes");
}
}
}
and my MainActivity code is
public class MainActivity extends AppCompatActivity {
private Toolbar mainToolbar;
private FirebaseAuth mAuth;
private FirebaseFirestore firebaseFirestore;
private String current_user_id;
private FloatingActionButton addPostBtn;
private HomeFragment homeFragment;
private BottomNavigationView mainbottomNav;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
firebaseFirestore = FirebaseFirestore.getInstance();
mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(mainToolbar);
getSupportActionBar().setTitle("Central Department of Physics");
mainToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent newPostIntent = new Intent(Main2Activity.this, MainActivity.class);
startActivity(newPostIntent);
}
});
mainbottomNav = findViewById(R.id.mainBottomNav);
// FRAGMENTS
homeFragment = new HomeFragment();
replaceFragment(homeFragment);
mainbottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.bottom_action_home :
replaceFragment(homeFragment);
return true;
case R.id.bottom_action_account:
return true;
case R.id.bottom_action_notif:
return true;
default:
return false;
}
}
});
addPostBtn = findViewById(R.id.add_post_btn);
addPostBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent newPostIntent = new Intent(Main2Activity.this, NewPostActivity.class);
startActivity(newPostIntent);
}
});
}
#Override
protected void onStart() {
super.onStart();
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
if(currentUser == null){
Intent loginIntent = new Intent(Main2Activity.this, LoginActivity.class);
startActivity(loginIntent);
finish();
} else {
current_user_id = mAuth.getCurrentUser().getUid();
firebaseFirestore.collection("Users").document(current_user_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()){
if(!task.getResult().exists()){
Intent setupIntent = new Intent(MainActivity.this, SetupActivity.class);
startActivity(setupIntent);
finish();
}
} else {
String errorMessage = task.getException().getMessage();
Toast.makeText(Main2Activity.this, "Error : " + errorMessage, Toast.LENGTH_LONG).show();
}
}
});
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_logout_btn:
logOut();
return true;
case R.id.action_settings_btn:
Intent settingsIntent = new Intent(MainActivity.this, SetupActivity.class);
startActivity(settingsIntent);
return true;
default:
return false;
}
}
private void logOut() {
mAuth.signOut();
sendToLogin();
}
private void sendToLogin() {
Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(loginIntent);
finish();
}
private void replaceFragment(Fragment fragment){
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_container, fragment);
fragmentTransaction.commit();
}
}
Here is the complete code https://github.com/akshayejh/PhotoBlog-Android-Blog-App
Check whether your activity is finishing before using Glide. Something like this:
if (!activity.isFinishing()) {
Glide.with(...
}

ExoPlayer onResume() Restore Playback State

I have implemented the Player and now there is a problem. When the video is playing and if the app is closed and resumed, the video screen freezes. I even saw the ExoPlayer Demo Activity from Google for better understanding but I could not get through it for implementing in my app. I have attached the Player Activity here and for the full code, I am sharing the GitHub repository for all files.
RecipeStepDetailFragment.java
package com.example.android.recipe.ui;
import android.content.Context;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.android.recipe.R;
import com.example.android.recipe.pojo.Recipe;
import com.example.android.recipe.pojo.Step;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import java.util.ArrayList;
import java.util.List;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveVideoTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import com.squareup.picasso.Picasso;
import static com.example.android.recipe.ui.RecipeActivity.SELECTED_INDEX;
import static com.example.android.recipe.ui.RecipeActivity.SELECTED_RECIPES;
import static com.example.android.recipe.ui.RecipeActivity.SELECTED_STEPS;
public class RecipeStepDetailFragment extends Fragment {
private SimpleExoPlayerView simpleExoPlayerView;
private SimpleExoPlayer player;
private BandwidthMeter bandwidthMeter;
private ArrayList<Step> steps = new ArrayList<>();
private int selectedIndex;
private Handler mainHandler;
ArrayList<Recipe> recipe;
String recipeName;
public RecipeStepDetailFragment() { }
private ListItemClickListener itemClickListener;
public interface ListItemClickListener {
void onListItemClick(List<Step> allSteps,int Index,String recipeName);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView textView;
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
itemClickListener =(RecipeDetailActivity)getActivity();
recipe = new ArrayList<>();
if(savedInstanceState != null) {
steps = savedInstanceState.getParcelableArrayList(SELECTED_STEPS);
selectedIndex = savedInstanceState.getInt(SELECTED_INDEX);
recipeName = savedInstanceState.getString("Title");
}
else {
steps =getArguments().getParcelableArrayList(SELECTED_STEPS);
if (steps!=null) {
steps =getArguments().getParcelableArrayList(SELECTED_STEPS);
selectedIndex=getArguments().getInt(SELECTED_INDEX);
recipeName=getArguments().getString("Title");
}
else {
recipe =getArguments().getParcelableArrayList(SELECTED_RECIPES);
steps=(ArrayList<Step>)recipe.get(0).getSteps();
selectedIndex=0;
}
}
View rootView = inflater.inflate(R.layout.recipe_step_detail_fragment_body_part, container, false);
textView = (TextView) rootView.findViewById(R.id.recipe_step_detail_text);
textView.setText(steps.get(selectedIndex).getDescription());
textView.setVisibility(View.VISIBLE);
simpleExoPlayerView = (SimpleExoPlayerView) rootView.findViewById(R.id.playerView);
simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
String videoURL = steps.get(selectedIndex).getVideoURL();
if (rootView.findViewWithTag("sw600dp-port-recipe_step_detail")!=null) {
recipeName=((RecipeDetailActivity) getActivity()).recipeName;
((RecipeDetailActivity) getActivity()).getSupportActionBar().setTitle(recipeName);
}
String imageUrl=steps.get(selectedIndex).getThumbnailURL();
if (imageUrl!="") {
Uri builtUri = Uri.parse(imageUrl).buildUpon().build();
ImageView thumbImage = (ImageView) rootView.findViewById(R.id.thumbImage);
Picasso.with(getContext()).load(builtUri).into(thumbImage);
}
if (!videoURL.isEmpty()) {
initializePlayer(Uri.parse(steps.get(selectedIndex).getVideoURL()));
if (rootView.findViewWithTag("sw600dp-land-recipe_step_detail")!=null) {
getActivity().findViewById(R.id.fragment_container2).setLayoutParams(new LinearLayout.LayoutParams(-1,-2));
simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH);
}
else if (isInLandscapeMode(getContext())){
textView.setVisibility(View.GONE);
}
}
else {
player=null;
simpleExoPlayerView.setForeground(ContextCompat.getDrawable(getContext(), R.drawable.ic_visibility_off_white_36dp));
simpleExoPlayerView.setLayoutParams(new LinearLayout.LayoutParams(300, 300));
}
Button mPrevStep = (Button) rootView.findViewById(R.id.previousStep);
Button mNextstep = (Button) rootView.findViewById(R.id.nextStep);
mPrevStep.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (steps.get(selectedIndex).getId() > 0) {
if (player!=null){
player.stop();
}
itemClickListener.onListItemClick(steps,steps.get(selectedIndex).getId() - 1,recipeName);
}
else {
Toast.makeText(getActivity(),"You already are in the First step of the recipe", Toast.LENGTH_SHORT).show();
}
}});
mNextstep.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int lastIndex = steps.size()-1;
if (steps.get(selectedIndex).getId() < steps.get(lastIndex).getId()) {
if (player!=null){
player.stop();
}
itemClickListener.onListItemClick(steps,steps.get(selectedIndex).getId() + 1,recipeName);
}
else {
Toast.makeText(getContext(),"You already are in the Last step of the recipe", Toast.LENGTH_SHORT).show();
}
}});
return rootView;
}
private void initializePlayer(Uri mediaUri) {
if (player == null) {
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
simpleExoPlayerView.setPlayer(player);
String userAgent = Util.getUserAgent(getContext(), "Baking App");
MediaSource mediaSource = new ExtractorMediaSource(mediaUri, new DefaultDataSourceFactory(getContext(), userAgent), new DefaultExtractorsFactory(), null, null);
player.prepare(mediaSource);
player.setPlayWhenReady(true);
}
}
#Override
public void onSaveInstanceState(Bundle currentState) {
super.onSaveInstanceState(currentState);
currentState.putParcelableArrayList(SELECTED_STEPS,steps);
currentState.putInt(SELECTED_INDEX,selectedIndex);
currentState.putString("Title",recipeName);
}
public boolean isInLandscapeMode( Context context ) {
return (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
}
#Override
public void onDetach() {
super.onDetach();
if (player!=null) {
player.stop();
player.release();
}
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (player!=null) {
player.stop();
player.release();
player=null;
}
}
#Override
public void onStop() {
super.onStop();
if (player!=null) {
player.stop();
player.release();
}
}
#Override
public void onPause() {
super.onPause();
if (player!=null) {
player.stop();
player.release();
}
}
}
Complete Project Repository: https://github.com/mtp2697/Udacity-AndroidDeveloperNanodegree-BakingApp
Help with the restoring of the state of video player for onPause() and onResume()
Thanks,
Praveen Thirumurugan.
I faced the same problem in my submission for the baking app and I did something like this:
private void initPlayer() {
// Exoplayer
// 1. Create a default TrackSelector
// Handler mainHandler = new Handler();
videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
RenderersFactory render = new DefaultRenderersFactory(getContext());
mainHandler = new Handler();
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
}
// 2. Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
recipeVideoPlayer = ExoPlayerFactory.newSimpleInstance(render, trackSelector, loadControl);
// exoPlayerView = (SimpleExoPlayerView) v.findViewById(R.id.exoplayer_recipe);
// Set media controller
mExoplayer.setUseController(true);
mExoplayer.setControllerVisibilityListener(this);
mExoplayer.requestFocus();
// Bind the player to the view.
mExoplayer.setPlayer(recipeVideoPlayer);
if (TextUtils.isEmpty(mSteps.getVideoURL())) {
mExoplayer.setVisibility(View.GONE);
} else {
mExoplayer.setVisibility(View.VISIBLE);
Uri video = Uri.parse(mSteps.getVideoURL());
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(getContext(), Util.getUserAgent(getContext(), "recipes"), null);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource videoSource = new ExtractorMediaSource(video, dataSourceFactory, extractorsFactory, mainHandler, null);
boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
recipeVideoPlayer.seekTo(resumeWindow, resumePosition);
}
recipeVideoPlayer.prepare(videoSource, !haveResumePosition, false);
recipeVideoPlayer.setPlayWhenReady(true);
recipeVideoPlayer.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
// Toast.makeText(getContext(), "Track changed" + trackSelections.length, Toast.LENGTH_SHORT).show();
//
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
clearResumePosition();
}
#Override
public void onPositionDiscontinuity() {
// updateResumePosition();
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
});
}
}
private void releasePlayer() {
if (recipeVideoPlayer != null) {
updateResumePosition();
recipeVideoPlayer.stop();
recipeVideoPlayer.release();
recipeVideoPlayer = null;
}
}
#Override
public void onResume() {
super.onResume();
if (recipeVideoPlayer == null) {
initPlayer();
}
}
#Override
public void onPause() {
super.onPause();
releasePlayer();
}
you can refer my project here

Categories