How to create audio foreground notification from recyclerview. any class - java

I hope you are all well. I've been having trouble with creating a notification service.
I have an audio app with recyclerviews and it's adapter class containing the viewholders. From the onBindviewholder I created an onclicklistener method that opens a player activity.
What I would like to happen is when you click on any item of the recyclerview, it starts the audio together with the foreground notification.
Please give your answers in written code as I am a novice in code jargon.
Thanks in advance.
Here's my code :
Player activity
public class Player extends AppCompatActivity implements MediaPlayer.OnCompletionListener {
TextView song_name, duration_played, total_duration;
ImageView nextbtn,prevbtn,shufflebtn,repeatbtn;
SeekBar seekBar;
FloatingActionButton playpausebtn;
Uri uri;
int position=-1;
int finalTime;
private cardhelper currentItem;
static MediaPlayer mMediaplayer;
static List<cardhelper>macam = new ArrayList<>();
private Handler handler = new Handler();
private Thread playThread, prevThread,nextThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
initViews();
getIntentMethod();
song_name.setText(macam.get(position).getSurah());
mMediaplayer.setOnCompletionListener(this);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mMediaplayer!=null && fromUser){
mMediaplayer.seekTo(progress * 1000);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
duration_played.setText(formattedTime(mCurrentposition));
finalTime = mMediaplayer.getDuration()/1000;
total_duration.setText(formattedTime(finalTime));
}
handler.postDelayed(this, 1000);
}
});
shufflebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(shuffleboolean){
shuffleboolean=false;
shufflebtn.setImageResource(R.drawable.ic_shuffle);
}else{
shuffleboolean=true;
shufflebtn.setImageResource(R.drawable.ic_shuffle_on);
}
}
});
repeatbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(repeatBoolean){
repeatBoolean=false;
repeatbtn.setImageResource(R.drawable.ic_repeat);
}else{
repeatBoolean=true;
repeatbtn.setImageResource(R.drawable.ic_repeat_on);
}
}
});
}
#Override
protected void onResume() {
playThreadbtn();
nextThreadbtn();
prevThreadbtn();
super.onResume();
}
private void playThreadbtn() {
playThread= new Thread(){
#Override
public void run() {
super.run();
playpausebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playpausebtnClicked();
}
});
}
};
playThread.start();
}
private void playpausebtnClicked() {
if(mMediaplayer.isPlaying()){
playpausebtn.setImageResource(R.drawable.ic_play);
mMediaplayer.pause();
seekBar.setMax(mMediaplayer.getDuration()/1000);
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
}
handler.postDelayed(this, 1000);
}
});
}else{
playpausebtn.setImageResource(R.drawable.ic_baseline_pause_24);
mMediaplayer.start();
seekBar.setMax(mMediaplayer.getDuration()/1000);
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
}
handler.postDelayed(this, 1000);
}
});
}
}
private void nextThreadbtn() {
nextThread= new Thread(){
#Override
public void run() {
super.run();
nextbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
nextbtnClicked();
}
});
}
};
nextThread.start();
}
private void nextbtnClicked() {
if(mMediaplayer.isPlaying()){
mMediaplayer.stop();
mMediaplayer.release();
if(shuffleboolean && !repeatBoolean){
position= getRandom(macam.size() - 1);
}
else if (! shuffleboolean && ! repeatBoolean){
position=((position + 1)% macam.size());
}
//else position will be position..
int cardhelper= macam.get(position).getAudio();
mMediaplayer= MediaPlayer.create(getApplicationContext(), cardhelper);
song_name.setText(macam.get(position).getSurah());
seekBar.setMax(mMediaplayer.getDuration()/1000);
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
}
handler.postDelayed(this, 1000);
}
});
mMediaplayer.setOnCompletionListener(this);
playpausebtn.setBackgroundResource(R.drawable.ic_baseline_pause_24);
mMediaplayer.start();
}else {
mMediaplayer.stop();
mMediaplayer.release();
if(shuffleboolean && !repeatBoolean){
position= getRandom(macam.size() - 1);
}
else if (! shuffleboolean && ! repeatBoolean){
position=((position + 1)% macam.size());
}
int cardhelper= macam.get(position).getAudio();
mMediaplayer= MediaPlayer.create(getApplicationContext(), cardhelper);
song_name.setText(macam.get(position).getSurah());
seekBar.setMax(mMediaplayer.getDuration()/1000);
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
}
handler.postDelayed(this, 1000);
}
});
mMediaplayer.setOnCompletionListener(this);
playpausebtn.setBackgroundResource(R.drawable.ic_play);
}
}
private int getRandom(int i) {
Random random = new Random();
return random.nextInt(i+ 1);
}
private void prevThreadbtn() {
prevThread= new Thread(){
#Override
public void run() {
super.run();
prevbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
prevbtnClicked();
}
});
}
};
prevThread.start();
}
private void prevbtnClicked() {
if(mMediaplayer.isPlaying()){
mMediaplayer.stop();
mMediaplayer.release();
position=((position-1) < 0 ? (macam.size() -1 ): (position - 1));
int cardhelper= macam.get(position).getAudio();
mMediaplayer= MediaPlayer.create(getApplicationContext(), cardhelper);
song_name.setText(macam.get(position).getSurah());
seekBar.setMax(mMediaplayer.getDuration()/1000);
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
}
handler.postDelayed(this, 1000);
}
});
mMediaplayer.setOnCompletionListener(this);
playpausebtn.setBackgroundResource(R.drawable.ic_baseline_pause_24);
mMediaplayer.start();
}else {
mMediaplayer.stop();
mMediaplayer.release();
position=((position-1) < 0 ? (macam.size() -1 ): (position - 1));
int cardhelper= macam.get(position).getAudio();
mMediaplayer= MediaPlayer.create(getApplicationContext(), cardhelper);
song_name.setText(macam.get(position).getSurah());
seekBar.setMax(mMediaplayer.getDuration()/1000);
Player.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaplayer!=null){
int mCurrentposition = mMediaplayer.getCurrentPosition()/1000;
seekBar.setProgress(mCurrentposition);
}
handler.postDelayed(this, 1000);
}
});
mMediaplayer.setOnCompletionListener(this);
playpausebtn.setBackgroundResource(R.drawable.ic_play);
}
}
private String formattedTime(int mCurrentposition) {
String totalout = "";
String totalNew = "";
String seconds = String.valueOf(mCurrentposition % 60);
String minutes = String.valueOf(mCurrentposition / 60);
totalout = minutes + ":" + seconds;
totalNew = minutes + ":" + "0" + seconds;
if(seconds.length() == 1){
return totalNew;
}
else {
return totalout;
}
}
private void getIntentMethod() {
position= getIntent().getIntExtra("position",-1);
macam=cardalbums;
macam=malbie;
if(macam!=null ){
playpausebtn.setImageResource(R.drawable.ic_baseline_pause_24);
currentItem = cardalbums.get(position);
currentItem = malbie.get(position);
}
if(mMediaplayer!=null){
mMediaplayer.stop();
mMediaplayer.release();
mMediaplayer= MediaPlayer.create(getApplicationContext(),currentItem.getAudio());
mMediaplayer.start();
}else{
mMediaplayer= MediaPlayer.create(getApplicationContext(),currentItem.getAudio());
mMediaplayer.start();
}
seekBar.setMax(mMediaplayer.getDuration()/ 1000);
}
private void initViews() {
song_name=findViewById(R.id.textTitle);
duration_played=findViewById(R.id.textCurrentTime);
total_duration=findViewById(R.id.textTotalTime);
nextbtn=findViewById(R.id.buttonNext);
prevbtn=findViewById(R.id.buttonPrevious);
shufflebtn=findViewById(R.id.buttonShuffle);
repeatbtn=findViewById(R.id.buttonRepeat);
seekBar=findViewById(R.id.playerSeekbar);
playpausebtn=findViewById(R.id.buttonPlay);
}
#Override
public void onCompletion(MediaPlayer mp) {
nextbtnClicked();
if(mMediaplayer!=null){
int cardhelper= macam.get(position).getAudio();
mMediaplayer= MediaPlayer.create(getApplicationContext(), cardhelper);
mMediaplayer.start();
mMediaplayer.setOnCompletionListener(this);
}
}
}
Fragment Adapter Class
public class musicadapter extends RecyclerView.Adapter<musicadapter.cardViewHolder>implements Filterable {
List<cardhelper> mcardalbums;
List<cardhelper>filteredData;
Filter filter;
int audio;
int position;
Context mcontext;
musicadapter(Context mcontext, List<cardhelper> mcardalbums) {
this.mcardalbums = mcardalbums;
this.mcontext=mcontext;
this.filteredData=mcardalbums;
}
#Override
public cardViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.card_design, parent, false);
cardViewHolder cvh= new cardViewHolder(v);
return cvh;
}
#Override
public void onBindViewHolder(#NonNull cardViewHolder holder, int position) {
cardhelper currentItem = mcardalbums.get(position);
holder.surah.setText(currentItem.getSurah());
holder.count.setText(currentItem.getNumOfSongs());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mcontext, Player.class);
intent.putExtra("position", position);
mcontext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mcardalbums.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mcardalbums = (List<cardhelper>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<cardhelper> filteredResults = null;
if (constraint.length() == 0) {
filteredResults = filteredData;
} else {
filteredResults = getFilteredResults(constraint.toString().toLowerCase());
}
FilterResults results = new FilterResults();
results.values = filteredResults;
return results;
}
};
}
protected List<cardhelper> getFilteredResults(String constraint) {
List<cardhelper> results = new ArrayList<>();
for (cardhelper item : filteredData) {
if (item.getSurah().toLowerCase().contains(constraint)) {
results.add(item);
}
}
return results;
}
public static class cardViewHolder extends RecyclerView.ViewHolder {
TextView count,surah;
#SuppressLint("ResourceType")
public cardViewHolder(View itemView) {
super(itemView);
count = itemView.findViewById(R.id.card_count);
surah = itemView.findViewById(R.id.card_surah);
}
}
}

so after a few weeks of research i found out how to this. Please bear in my I'm a novice but this is what i got from my observation:
You don't need a Service Class to create a notification because it can be created anywhere and called from button clicks inside a method. It will obligatorily need a channel, and addAction button to appear:
public void showNotification(int playpausebtn) {
final Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.new_disc);
macam= (ArrayList<cardhelper>) malbie;
macam= (ArrayList<cardhelper>) cardalbums;
if (macam != null) {
currentItem = malbie.get(position);
currentItem = cardalbums.get(position);
}
Intent previousIntent = new Intent(ACTION_PREVIOUS);
previousIntent.setAction(ACTION_PREVIOUS);
PendingIntent ppreviousIntent = PendingIntent.getBroadcast(this, 1, previousIntent, 0);
Intent playIntent = new Intent(ACTION_PLAY);
playIntent.setAction(ACTION_PLAY);
PendingIntent pplayIntent = PendingIntent.getBroadcast(this, 2, playIntent, 0);
Intent nextIntent = new Intent(ACTION_NEXT);
nextIntent.setAction(ACTION_NEXT);
PendingIntent pnextIntent = PendingIntent.getBroadcast(this, 3, nextIntent, 0);
// Create a new MediaSession
final MediaSession mediaSession = new MediaSession(this, "debug tag");
// Update the current metadata
mediaSession.setMetadata(new MediaMetadata.Builder()
.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, icon)
.putString(MediaMetadata.METADATA_KEY_ARTIST, "Pink Floyd")
.putString(MediaMetadata.METADATA_KEY_TITLE, "The Great Gig in the Sky")
.build());
// Indicate you're ready to receive media commands:
Intent intentOpenApp = new Intent(getApplicationContext(), Userxui.class);
PendingIntent pendingIntentOpenApp = PendingIntent.getActivity(getApplicationContext(), 0,
intentOpenApp, 0);
// Create a new Notification
NotificationCompat.Builder noti = new NotificationCompat.Builder(getApplicationContext(), "CHANNEl_ID");
// Hide the timestamp
noti.setShowWhen(false);
noti.setLargeIcon(icon);
noti.setVisibility(androidx.core.app.NotificationCompat.VISIBILITY_PUBLIC);
// Set the Notification style
noti.setContentTitle(currentItem.getSurah());
noti.addAction(R.drawable.ic_previous, "previous", ppreviousIntent);
noti.addAction(playpausebtn, "pause", pplayIntent);
noti.addAction(R.drawable.ic_next, "next", pnextIntent);
noti.setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(MediaSessionCompat.Token.fromToken(mediaSession.getSessionToken())));
noti.setContentIntent(pendingIntentOpenApp);
noti.setSmallIcon(R.drawable.only);
noti.setOnlyAlertOnce(true);
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"Siraa",
NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
noti.setChannelId(CHANNEL_ID);
}
notificationManager.notify(0, noti.build());
}
To implement notification action button you need to create Strings :
public static final String ACTION_PLAY = "action_play";
public static final String ACTION_NEXT = "action_next";
public static final String ACTION_PREVIOUS = "action_previous";
public static final String CHANNEL_ID = "Channel1";
NotificationManager notificationManager;
3.Register these actions inside a Broadcast receiver with intentfilters:
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_PLAY);
filter.addAction(ACTION_NEXT);
filter.addAction(ACTION_PREVIOUS);
receiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String actioname = intent.getAction();
if(actioname!=null){
switch (actioname){
case ACTION_PLAY:
Toast.makeText(context,"Click play",Toast.LENGTH_SHORT).show();
\\\ implement whatever
playpausebtnClicked();
break;
case ACTION_NEXT:
Toast.makeText(context,"Clicked next",Toast.LENGTH_SHORT).show();
nextbtnClicked();
break;
case ACTION_PREVIOUS:
Toast.makeText(context,"Clicked previous",Toast.LENGTH_SHORT).show();
prevbtnClicked();
break;
}
}
}
};
registerReceiver(receiver,filter);
and open themethod in my buttonclick event.
That's it no need to register in the manifest file. Hope this helped.

Related

Is there any method to track or play the audio items which is in recyclerview outside the activity?

Everytime I click on the nextBTn and PrevBtn in "music player activity",the next/previous Items in the recyclerview of "songs activity" or it's adapter need to play the perticuclar song in "Player activity".
I tried to make position++ and position-- but the items need to save in player activity I guess.
How can I play next and previous song when my player activity and adapter are two different activities.
How can I give the recyclerview items of the song currently playing and apply previoussongBTn,nextsongBTn?
code of player.java
public class player extends AppCompatActivity {
private ImageView imagePlayPause, forwardBtn, backwardBtn;
MediaPlayer mediaPlayer;
ImageView songImageIV;
String song_path,image_path,song_name,album_name,sng_path,pre_song;
TextView song_nameTV,albumNameTV;
private SeekBar playerSeekBar;
private TextView textCurrentTime, textTotalDuration;
private Handler handler = new Handler();
AdapterSongs songAdapter;
private int seekForwardTime = 10 * 1000;
private int seekBackwardTime = 10 * 1000; // default 10 second
private ChipNavigationBar chipNavigationBar;//for navigation
TextView scrollingText;//song name which scrolls horizontally
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.player_activity);
songImageIV = findViewById(R.id.song_image);
song_nameTV = findViewById(R.id.tv_songName);
albumNameTV = findViewById(R.id.topBarAlbumName);
textCurrentTime = findViewById(R.id.current_time);
textTotalDuration = findViewById(R.id.totalDuration);
playerSeekBar = findViewById(R.id.seekbar);
imagePlayPause = findViewById(R.id.playbtn);
forwardBtn = findViewById(R.id.forwardBtn);
backwardBtn = findViewById(R.id.backwardBtn);
mediaPlayer = playerInstance.getInstance();
playerSeekBar.setMax(100);
SharedPreferences sharedPreferences = getSharedPreferences("songDetails",MODE_PRIVATE);
song_path = sharedPreferences.getString("songPath","");
image_path = sharedPreferences.getString("album_img","");
song_name = sharedPreferences.getString("songName","");
album_name = sharedPreferences.getString("album_name","");
pre_song = sharedPreferences.getString("pre_song","");
// albumNameTV.append(album_name);
Picasso.get().load(image_path).into(songImageIV);
song_nameTV.setText(song_name);
albumNameTV.append(album_name);
scrollingText = (TextView)findViewById(R.id.tv_songName);
scrollingText.setSelected(true);
Log.i("tagconvertstr", "[song_path = " +song_path + "]");
Log.i("tagconvertstr", "[pre_path" + pre_song + "]");
if(!song_path.equals(pre_song))
{
prepareMediaPlayer();
textTotalDuration.setText(milisecToTimer(mediaPlayer.getDuration()));
if(!mediaPlayer.isPlaying()){
prepareMediaPlayer();
}
}
if(mediaPlayer.isPlaying())
{
imagePlayPause.setImageResource(R.drawable.pause_icon);
updater.run();
textTotalDuration.setText(milisecToTimer(mediaPlayer.getDuration()));
}
if(song_path.equalsIgnoreCase(pre_song))
{
updater.run();
textTotalDuration.setText(milisecToTimer(mediaPlayer.getDuration()));
}
navigation();//for navigation
imagePlayPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
playpause();
}
});
playerSeekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
SeekBar seekBar = (SeekBar) view;
int playPosition = (mediaPlayer.getDuration()/100)*seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
textCurrentTime.setText(milisecToTimer(mediaPlayer.getCurrentPosition()));
return false;
}
});
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
playerSeekBar.setSecondaryProgress(i);
}
});
if(mediaPlayer!=null) {
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.stop();
mediaPlayer.reset();
prepareMediaPlayer();
playerSeekBar.setProgress(0);
imagePlayPause.setImageResource(R.drawable.pause_icon);
textCurrentTime.setText(R.string.zero);
textTotalDuration.setText(R.string.zero);
}
});
}
forwardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
forwardSong();
}
});
backwardBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rewindSong();
}
});
}
public void forwardSong() {
if (mediaPlayer != null) {
int currentPosition = mediaPlayer.getCurrentPosition();
if (currentPosition + seekForwardTime <= mediaPlayer.getDuration()) {
mediaPlayer.seekTo(currentPosition + seekForwardTime);
} else {
mediaPlayer.seekTo(mediaPlayer.getDuration());
}
}
}
public void rewindSong() {
if (mediaPlayer != null) {
int currentPosition = mediaPlayer.getCurrentPosition();
if (currentPosition - seekBackwardTime >= 0) {
mediaPlayer.seekTo(currentPosition - seekBackwardTime);
} else {
mediaPlayer.seekTo(0);
}
}
}
private void prepareMediaPlayer(){
mediaPlayer.reset();
pre_song = song_path;
SharedPreferences sharedPreferences = getSharedPreferences("songDetails",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("pre_song",pre_song);
editor.apply();
imagePlayPause.setImageResource(R.drawable.pause_icon);
try{
mediaPlayer.setDataSource(song_path);
// mediaPlayer.setDataSource("https://testing-ariya.s3.ap-south-1.amazonaws.com/Faded_320(PaglaSongs).mp3");
mediaPlayer.prepare();
textTotalDuration.setText(milisecToTimer(mediaPlayer.getDuration()));
mediaPlayer.start();
updater.run();
}catch (Exception e){
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public Runnable updater = new Runnable() {
#Override
public void run() {
updateseekbar();
long currentDuration = mediaPlayer.getCurrentPosition();
textCurrentTime.setText(milisecToTimer(currentDuration));
}
};
public void updateseekbar(){
if(mediaPlayer.isPlaying()){
playerSeekBar.setProgress((int) (((float) mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration()) *100));
handler.postDelayed(updater,1000);
}
}
private String milisecToTimer(long milliseconds){
String timerString= "";
String secondsString;
int hours = (int) (milliseconds/(1000*60*60));
int minutes = (int) (milliseconds % (1000*60*60))/ (1000*60);
int seconds = (int) ((milliseconds%(1000*60*60))%(1000*60)/1000);
if (hours > 0) {
timerString = hours + ":";
}
if (seconds<10){
secondsString = "0" +seconds;
}else{
secondsString = ""+seconds;
}
timerString = timerString+minutes+":"+secondsString;
return timerString;
}
public void navigation() {
chipNavigationBar = findViewById(R.id.chipNavigation);
chipNavigationBar.setItemSelected(R.id.player, true);
//getSupportFragmentManager().beginTransaction().replace(R.id.container, new HomeFragment()).commit();
chipNavigationBar.setOnItemSelectedListener(new ChipNavigationBar.OnItemSelectedListener() {
#Override
public void onItemSelected(int i) {
switch (i) {
case R.id.home:
startActivity(new Intent(getApplicationContext(), MainActivity.class));
overridePendingTransition(0, 0);
finish();
return ;
case R.id.player:
return ;
}
}
});
}
public void playpause()
{
if(mediaPlayer.isPlaying()){
handler.removeCallbacks(updater);
mediaPlayer.pause();
imagePlayPause.setImageResource(R.drawable.play_icon);
}else{
imagePlayPause.setImageResource(R.drawable.pause_icon);
mediaPlayer.start();
updateseekbar();
}
}
}
code of Adaptersongs.java
public class AdapterSongs extends RecyclerView.Adapter<AdapterSongs.ViewHolder2>{
public List<SongsModelClass> songsModelClassList;
Context context;
Dialog customDialog;
public int selectedPosition;//for next and prev song playing
public AdapterSongs(List<SongsModelClass> songsModelClassList, Context context) {
super();
this.songsModelClassList = songsModelClassList;
this.context = context;
}
#NonNull
#Override
public ViewHolder2 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_song_row,parent,false);
ViewHolder2 viewHolder2 = new ViewHolder2(view);
return viewHolder2;
}
#Override
public void onBindViewHolder(#NonNull AdapterSongs.ViewHolder2 holder2, int position) {
SongsModelClass songData = songsModelClassList.get(position);
holder2.title.setText(songData.getTitle());
//Picasso.get().load(albumdata.getArtworkPath()).into(holder2.thumbnail);
holder2.title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences sharedPreferences1 = context.getSharedPreferences("login",Context.MODE_PRIVATE);
String userType = sharedPreferences1.getString("subscription","");
Log.i("tagconvertstr", "[userType" + userType + "]");
if(songData.getSongType().equalsIgnoreCase("YES")&&userType.equalsIgnoreCase("NO"))
{
customDialog = new Dialog(context);
customDialog.setContentView(R.layout.premium_alert_box);
customDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
customDialog.setCancelable(false);
customDialog.show();
TextView cancel = customDialog.findViewById(R.id.changeEmail);
TextView subscribe = customDialog.findViewById(R.id.confirmEmail);
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customDialog.dismiss();
}
});
subscribe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context,PremiumScreen.class);
context.startActivity(i);
customDialog.dismiss();
}
});
return;
}
Log.i("tagconvertstr", "[" + songData.getPath() + "]");
Intent intent = new Intent(context,player.class);
intent.putExtra("song_name",songData.getTitle());
intent.putExtra("song_path",songData.getPath());
intent.putExtra("album_img",songData.getArtworkPath());
intent.putExtra("album_name",songData.getSongAlbum());
SharedPreferences sharedPreferences = context.getSharedPreferences("songDetails",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("songPath",songData.getPath());
editor.putString("songName",songData.getTitle());
editor.putString("album_img",songData.getArtworkPath());
editor.putString("album_name",songData.getSongAlbum());
editor.apply();
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return songsModelClassList.size();
}
class ViewHolder2 extends RecyclerView.ViewHolder{
// ImageView thumbnail;
TextView title;
TextView id;
public ViewHolder2(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.song_title);
}
}
}

How can I make SeekBar indicate current position even when the app is resumed?

When the audio player app is resumed while playing audio, the SeekBar resets to 0. During audio playback, the SeekBar updates progress. However, when the screen is resumed, the SeekBar starts from the beginning without indicating the player's current position. When you press the pause button and then press the play button, it plays at the current position again. In updateProgress() method, there is long currentPosition = mLastPlaybackState.getPosition(); I think this code doesn't indicate the current position when resumed.
I implemented SeekBar update progress based on the UAMP FullScreenActivity
This is my NowPlayingAcitivy.java:
private PlaybackStateCompat mLastPlaybackState;
private final Handler mHandler = new Handler();
private final Runnable mUpdateProgressTask = new Runnable() {
#Override
public void run() {
updateProgress();
}
};
private final ScheduledExecutorService mExecutorService =
Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> mScheduledFuture;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNowPlayingBinding = DataBindingUtil.setContentView(
this, R.layout.activity_now_playing);
createMediaBrowserCompat();
mNowPlayingBinding.playingInfo.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mNowPlayingBinding.playingInfo.tvStart.setText(DateUtils.formatElapsedTime(
progress/1000));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Cancel the future returned by scheduleAtFixedRate() to stop the SeekBar from progressing
stopSeekbarUpdate();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
MediaControllerCompat.getMediaController(NowPlayingActivity.this)
.getTransportControls().seekTo(seekBar.getProgress());
// Create and execute a periodic action to update the SeekBar progress
scheduleSeekbarUpdate();
}
});
}
private void createMediaBrowserCompat() {
mMediaBrowser = new MediaBrowserCompat(this,
new ComponentName(this, PodcastService.class),
mConnectionCallbacks,
null);
}
#Override
protected void onStart() {
super.onStart();
mMediaBrowser.connect();
}
#Override
protected void onResume() {
super.onResume();
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
#Override
protected void onStop() {
super.onStop();
if (MediaControllerCompat.getMediaController(this) != null) {
MediaControllerCompat.getMediaController(this).unregisterCallback(controllerCallback);
}
mMediaBrowser.disconnect();
}
#Override
protected void onDestroy() {
super.onDestroy();
stopSeekbarUpdate();
mExecutorService.shutdown();
}
private final MediaBrowserCompat.ConnectionCallback mConnectionCallbacks =
new MediaBrowserCompat.ConnectionCallback() {
#Override
public void onConnected() {
MediaSessionCompat.Token token = mMediaBrowser.getSessionToken();
MediaControllerCompat mediaController = null;
try {
mediaController = new MediaControllerCompat(NowPlayingActivity.this, token);
} catch (RemoteException e) {
Timber.e("Error creating media controller");
}
MediaControllerCompat.setMediaController(NowPlayingActivity.this,
mediaController);
buildTransportControls();
}
#Override
public void onConnectionSuspended() {
super.onConnectionSuspended();
}
#Override
public void onConnectionFailed() {
super.onConnectionFailed();
}
};
void buildTransportControls() {
mNowPlayingBinding.playingInfo.ibPlayPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PlaybackStateCompat pbState =
MediaControllerCompat.getMediaController(NowPlayingActivity.this).getPlaybackState();
if (pbState != null) {
MediaControllerCompat.TransportControls controls =
MediaControllerCompat.getMediaController(NowPlayingActivity.this).getTransportControls();
switch (pbState.getState()) {
case PlaybackStateCompat.STATE_PLAYING: // fall through
case PlaybackStateCompat.STATE_BUFFERING:
controls.pause();
stopSeekbarUpdate();
break;
case PlaybackStateCompat.STATE_PAUSED:
case PlaybackStateCompat.STATE_STOPPED:
controls.play();
scheduleSeekbarUpdate();
break;
default:
Timber.d("onClick with state " + pbState);
}
}
}
});
MediaControllerCompat mediaController =
MediaControllerCompat.getMediaController(NowPlayingActivity.this);
MediaMetadataCompat metadata = mediaController.getMetadata();
PlaybackStateCompat pbState = mediaController.getPlaybackState();
updatePlaybackState(pbState);
if (metadata != null) {
// Get the episode duration from the metadata and sets the end time to the textView
updateDuration(metadata);
}
// Set the current progress to the current position
updateProgress();
if (pbState != null && (pbState.getState() == PlaybackStateCompat.STATE_PLAYING ||
pbState.getState() == PlaybackStateCompat.STATE_BUFFERING)) {
scheduleSeekbarUpdate();
}
mediaController.registerCallback(controllerCallback);
}
MediaControllerCompat.Callback controllerCallback = new MediaControllerCompat.Callback() {
#Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
super.onMetadataChanged(metadata);
if (metadata != null) {
updateDuration(metadata);
}
}
#Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
super.onPlaybackStateChanged(state);
// Update the playback state
updatePlaybackState(state);
}
};
/**
* Creates and executes a periodic action that becomes enabled first after the given initial delay,
* and subsequently with the given period;that is executions will commence after initialDelay
* then initialDelay + period, then initialDelay + 2 * period, and so on.
*/
private void scheduleSeekbarUpdate() {
stopSeekbarUpdate();
if (!mExecutorService.isShutdown()) {
mScheduleFuture = mExecutorService.scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
mHandler.post(mUpdateProgressTask);
}
}, 100,
1000, TimeUnit.MILLISECONDS);
}
}
/**
* Cancels the future returned by scheduleAtFixedRate() to stop the SeekBar from progressing.
*/
private void stopSeekbarUpdate() {
if (mScheduledFuture != null) {
mScheduledFuture.cancel(false);
}
}
/**
* Gets the episode duration from the metadata and sets the end time to be displayed in the TextView.
*/
private void updateDuration(MediaMetadataCompat metadata) {
if (metadata == null) {
return;
}
int duration = (int) metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)
* 1000;
mNowPlayingBinding.playingInfo.seekBar.setMax(duration);
mNowPlayingBinding.playingInfo.tvEnd.setText(
DateUtils.formatElapsedTime(duration / 1000));
}
/**
* Calculates the current position (distance = timeDelta * velocity) and sets the current progress
* to the current position.
*/
private void updateProgress() {
if (mLastPlaybackState == null) {
return;
}
long currentPosition = mLastPlaybackState.getPosition();
if (mLastPlaybackState.getState() == PlaybackStateCompat.STATE_PLAYING) {
// Calculate the elapsed time between the last position update and now and unless
// paused, we can assume (delta * speed) + current position is approximately the
// latest position. This ensure that we do not repeatedly call the getPlaybackState()
// on MediaControllerCompat.
long timeDelta = SystemClock.elapsedRealtime() -
mLastPlaybackState.getLastPositionUpdateTime();
currentPosition += (int) timeDelta * mLastPlaybackState.getPlaybackSpeed();
}
mNowPlayingBinding.playingInfo.seekBar.setProgress((int) currentPosition);
}
private void updatePlaybackState(PlaybackStateCompat state) {
if (state == null) {
return;
}
mLastPlaybackState = state;
switch (state.getState()) {
case PlaybackStateCompat.STATE_PLAYING:
hideLoading();
mNowPlayingBinding.playingInfo.ibPlayPause.setImageResource(R.drawable.exo_controls_pause);
scheduleSeekbarUpdate();
break;
case PlaybackStateCompat.STATE_PAUSED:
hideLoading();
mNowPlayingBinding.playingInfo.ibPlayPause.setImageResource(R.drawable.exo_controls_play);
stopSeekbarUpdate();
break;
case PlaybackStateCompat.STATE_NONE:
case PlaybackStateCompat.STATE_STOPPED:
hideLoading();
mNowPlayingBinding.playingInfo.ibPlayPause.setImageResource(R.drawable.exo_controls_play);
stopSeekbarUpdate();
break;
case PlaybackStateCompat.STATE_BUFFERING:
showLoading();
mNowPlayingBinding.playingInfo.ibPlayPause.setImageResource(R.drawable.exo_controls_play);
stopSeekbarUpdate();
break;
default:
Timber.d("Unhandled state " + state.getState());
}
}
This is my PodcastService.java:
public class PodcastService extends MediaBrowserServiceCompat implements Player.EventListener {
#Override
public void onCreate() {
super.onCreate();
initializeMediaSession();
}
private void initializeMediaSession() {
mMediaSession = new MediaSessionCompat(PodcastService.this, TAG);
mMediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_REWIND |
PlaybackStateCompat.ACTION_FAST_FORWARD |
PlaybackStateCompat.ACTION_PLAY_PAUSE);
mMediaSession.setPlaybackState(mStateBuilder.build());
mMediaSession.setCallback(new MySessionCallback());
setSessionToken(mMediaSession.getSessionToken());
mMediaSession.setSessionActivity(PendingIntent.getActivity(this,
11,
new Intent(this, NowPlayingActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT));
}
private void initializePlayer() {
if (mExoPlayer == null) {
DefaultRenderersFactory defaultRenderersFactory = new DefaultRenderersFactory(this);
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
mExoPlayer = ExoPlayerFactory.newSimpleInstance(this, defaultRenderersFactory,
trackSelector, loadControl);
mExoPlayer.addListener(this);
// Prepare the MediaSource
Uri mediaUri = Uri.parse(mUrl);
MediaSource mediaSource = buildMediaSource(mediaUri);
mExoPlayer.prepare(mediaSource);
mExoPlayer.setPlayWhenReady(true);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null || intent.getAction() == null) {
Timber.e("intent in onStartCommand is null");
return START_STICKY;
}
// Check if the old player should be released
if (intent.getAction() != null && intent.getAction().equals(ACTION_RELEASE_OLD_PLAYER)) {
if (mExoPlayer != null) {
mExoPlayer.stop();
releasePlayer();
}
}
Bundle b = intent.getBundleExtra(EXTRA_ITEM);
if (b != null) {
mItem = b.getParcelable(EXTRA_ITEM);
mUrl = mItem.getEnclosures().get(0).getUrl();
}
initializePlayer();
// Convert hh:mm:ss string to seconds to put it into the metadata
long duration = PodUtils.getDurationInMilliSeconds(mItem);
MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration).build();
mMediaSession.setMetadata(metadata);
return START_STICKY;
}
private void releasePlayer() {
mExoPlayer.release();
mExoPlayer = null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
if (mExoPlayer != null) {
mExoPlayer.stop(true);
}
stopSelf();
}
#Override
public void onDestroy() {
mMediaSession.release();
releasePlayer();
super.onDestroy();
}
private MediaSource buildMediaSource(Uri mediaUri) {
String userAgent = Util.getUserAgent(this, getString(R.string.app_name));
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
this, userAgent);
CacheDataSourceFactory cacheDataSourceFactory =
new CacheDataSourceFactory(
DownloadUtil.getCache(this),
dataSourceFactory,
CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
return new ExtractorMediaSource.Factory(cacheDataSourceFactory).createMediaSource(mediaUri);
}
#Nullable
#Override
public BrowserRoot onGetRoot(#NonNull String clientPackageName, int clientUid,
#Nullable Bundle rootHints) {
return new BrowserRoot("pod_root_id", null);
}
#Override
public void onLoadChildren(#NonNull String parentMediaId,
#NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
// Browsing not allowed
if (TextUtils.equals("empty_root_id", parentMediaId)) {
result.sendResult(null);
return;
}
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
// Check if this is the root menu:
if ("pod_root_id".equals(parentMediaId)) {
// Build the MediaItem objects for the top level,
// and put them in the mediaItems list...
} else {
// Examine the passed parentMediaId to see which submenu we're at,
// and put the children of that menu in the mediaItems list...
}
result.sendResult(mediaItems);
}
private class MySessionCallback extends MediaSessionCompat.Callback {
#Override
public void onPlay() {
startService(new Intent(getApplicationContext(), PodcastService.class));
mMediaSession.setActive(true);
// Start the player
if (mExoPlayer != null) {
mExoPlayer.setPlayWhenReady(true);
}
}
#Override
public void onPause() {
mExoPlayer.setPlayWhenReady(false);
stopForeground(false);
}
#Override
public void onRewind() {
mExoPlayer.seekTo(Math.max(mExoPlayer.getCurrentPosition() - 10000, 0));
}
#Override
public void onFastForward() {
long duration = mExoPlayer.getDuration();
mExoPlayer.seekTo(Math.min(mExoPlayer.getCurrentPosition() + 30000, duration));
}
#Override
public void onStop() {
stopSelf();
mMediaSession.setActive(false);
mExoPlayer.stop();
stopForeground(true);
}
#Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
if (mExoPlayer != null) {
mExoPlayer.seekTo((int) pos);
}
}
}
// Player Event Listeners
#Override
public void onTimelineChanged(Timeline timeline, #Nullable Object manifest, int reason) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_IDLE) {
mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED,
mExoPlayer.getCurrentPosition(), 1f);
} else if (playbackState == Player.STATE_BUFFERING) {
mStateBuilder.setState(PlaybackStateCompat.STATE_BUFFERING,
mExoPlayer.getCurrentPosition(), 1f);
} else if (playbackState == Player.STATE_READY && playWhenReady) {
mStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING,
mExoPlayer.getCurrentPosition(), 1f);
Timber.d("onPlayerStateChanged: we are playing");
} else if (playbackState == Player.STATE_READY) {
mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED,
mExoPlayer.getCurrentPosition(), 1f);
Timber.d("onPlayerStateChanged: we are paused");
} else if (playbackState == Player.STATE_ENDED) {
mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED,
mExoPlayer.getCurrentPosition(), 1f);
} else {
mStateBuilder.setState(PlaybackStateCompat.STATE_NONE,
mExoPlayer.getCurrentPosition(), 1f);
}
mMediaSession.setPlaybackState(mStateBuilder.build());
}
}
Edit: The full source code is available here.
To set the state progress based on value should use setProgress(value) method.
when paused the music save value from seekBar as an Integer, then when resume it get that value and put it as a parameter in setProgress() method.
when you pause music to save the value:
#Override
protected void onPause() {
super.onPause();
mSeekBarRate.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
int progress = 0;
#Override
public void onProgressChanged(SeekBar mSeekBarRate, int progressValue, boolean fromUser) {
progress = progressValue;
}
#Override
public void onStartTrackingTouch(SeekBar mSeekBarRate) {
}
#Override
public void onStopTrackingTouch(SeekBar mSeekBarRate) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("value", progress);
}
});
}
when you resume music retrieve that value:
#Override
protected void onStart() {
super.onStart();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int value = prefs.getInt("value", 0);
mSeekBarRate.setProgress(value);
}
Hope it Helps you.

Seekbar progress changed in RecyclerView

Problem:
I have recyclerview and mediaplayer
I have many seekbars (managed by RecyclerView.Adapter),By changing the seekbar of one row item , it automatically change the seekbar of previous or next row.
Main problem is second last item of recyclerview is playing the song and i change the last item's seekbar ,it also change the second last item's seekbar.
I'm guessing two views are using the same reference .
#ViewholderClass
public class AudioViewHolder extends BaseHolder<ChatViewModelList> {
private Context context;
TextView tvTimestamp;
ImageView ivUser;
private final TextView startTime;
static PlayAudioFragment playAudioFragment;
private View loadingAudio;
private ImageView playAudio;
private TextView durationAudio;
private SeekBar progressAudio;
public AudioViewHolder(View itemView, Context context, PlayAudioFragment playAudioFragment) {
super(itemView);
this.context = context;
tvTimestamp = (TextView) itemView.findViewById(R.id.ImgTime);
ivUser = (ImageView) itemView.findViewById(R.id.ContactListIcon);
this.playAudioFragment = playAudioFragment;
loadingAudio = itemView.findViewById(R.id.chatMessageLoadingAudio);
playAudio = (ImageView) itemView.findViewById(R.id.chatMessagePlayAudio);
progressAudio = (SeekBar) itemView.findViewById(R.id.chatMessageProgressAudio);
durationAudio = (TextView) itemView.findViewById(R.id.chatMessageDurationAudio);
startTime = (TextView) itemView.findViewById(R.id.startTime);
}
#Override
public void BindData(final ChatViewModelList model) {
setIvUser(model.getMessage().getUserModel().getPhoto_profile());
setTvTimestamp(model.getMessage().getTimeStamp());
if (model.getMessage().getFileModel().getType().equals(Media.Type.Audio)) {
startTime.setText(TimeFormatter.getDurationString(0));
progressAudio.setProgress(0);
progressAudio.setMax(100);
playAudio.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FileModel fileModel = model.getMessage().getFileModel();
if (playAudioFragment.isStopped() || !playAudioFragment.getCurrentMedia().equals(fileModel)) {
playAudioFragment.resetPlayback();
playAudioFragment.setCustomPlayback(playAudio, durationAudio, loadingAudio, progressAudio);
playAudioFragment.loadNewMedia(fileModel);
} else {
playAudioFragment.togglePlayback();
}
}
});
if (!model.getMessage().getFileModel().equals(playAudioFragment.getCurrentMedia())) {
loadingAudio.setVisibility(View.GONE);
progressAudio.setProgress(0);
playAudio.setImageResource(R.drawable.ic_play_arrow_blue_36dp);
int duration = (int) model.getMessage().getFileModel().getDuration();
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration);
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
- TimeUnit.MINUTES.toSeconds(minutes);
durationAudio.setText(String.format("%02d:%02d", minutes, seconds));
if (playAudioFragment.isPlayView(playAudio)) {
playAudioFragment.resetPlayback();
}
} else {
playAudioFragment.setCustomPlayback(playAudio, durationAudio, loadingAudio, progressAudio);
}
}
}
public void setIvUser(String urlPhotoUser) {
if (ivUser == null) return;
Glide.with(ivUser.getContext()).load(urlPhotoUser).centerCrop().placeholder(R.drawable.ic_menu_camera).transform(new CircleTransform(ivUser.getContext())).override(40, 40).into(ivUser);
}
public void setTvTimestamp(String timestamp) {
if (tvTimestamp == null) return;
tvTimestamp.setText(DateUtils.convertMillisecondsToTime(Long.valueOf(timestamp)));
}
}
And code of Fragment for playing audio.
public class PlayAudioFragment extends DialogFragment {
public static final String TAG = "RecordAudioFragment";
public static final int MAX_DURATION_MS = 50 * 1000;
public static final int IDLE_STATUS = 0;
public static final int READY_STATUS = 2;
public static final int PLAYER_STATUS = 3;
public static final int PLAYING_STATUS = 0;
public static final int PAUSED_STATUS = 1;
public static final int STOPPED_STATUS = 2;
public static final String EXTRA_MEDIA = "media";
public TextView startTime;
public TextView endTime;
public ImageView play;
public SeekBar progress;
public TextView mainAction;
public TextView cancel;
public View loadingContainer;
public Handler handler;
public static File recordedAudio;
public MediaRecorder mediaRecorder;
public MediaPlayer mediaPlayer;
public int recordingStatus = IDLE_STATUS;
public int playbackStatus = STOPPED_STATUS;
public int duration = 0;
public CountDownTimer timer;
private RelativeLayout root;
private FileModel media;
public static PlayAudioFragment newInstance(Media media) {
Bundle args = new Bundle();
args.putParcelable(EXTRA_MEDIA, media);
PlayAudioFragment fragment = new PlayAudioFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_record_audio, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setupObjects();
setupView(view);
setupDataIfExists();
}
public void setupDataIfExists() {
Bundle args = getArguments();
if (args != null && args.containsKey(EXTRA_MEDIA)) {
media = args.getParcelable(EXTRA_MEDIA);
switchRecordingStatus(PLAYER_STATUS);
root.setVisibility(View.VISIBLE);
}
}
public void setupView(View view) {
loadingContainer = view.findViewById(R.id.loadingContainer);
endTime = (TextView) view.findViewById(R.id.endTime);
endTime.setText(TimeFormatter.getDurationStringFromMillis(MAX_DURATION_MS));
startTime = (TextView) view.findViewById(R.id.startTime);
progress = (SeekBar) view.findViewById(R.id.progress);
root = (RelativeLayout) view.findViewById(R.id.root);
play = (ImageView) view.findViewById(R.id.play);
play.setOnClickListener(onPlayClickListener);
setCustomPlayback(play, startTime, loadingContainer, progress);
mainAction = (TextView) view.findViewById(R.id.mainAction);
cancel = (TextView) view.findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
}
});
}
public void setCustomPlayback(ImageView play, TextView duration, View loadingContainer, SeekBar progress) {
this.loadingContainer = loadingContainer;
this.startTime = duration;
this.startTime.setText(TimeFormatter.getDurationString(0));
this.play = play;
this.progress = progress;
this.progress.setOnSeekBarChangeListener(onSeekBarChangeListener);
setupObjects();
if (recordingStatus == PLAYER_STATUS) {
switchPlaybackStatus(PLAYING_STATUS);
handler.post(playRunnable);
}
}
public SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mediaPlayer != null && fromUser) {
mediaPlayer.seekTo(progress);
handler.removeCallbacks(playRunnable);
long minutes = TimeUnit.MILLISECONDS.toMinutes(mediaPlayer.getCurrentPosition());
long seconds = TimeUnit.MILLISECONDS.toSeconds(mediaPlayer.getCurrentPosition())
- TimeUnit.MINUTES.toSeconds(minutes);
startTime.setText(String.format("%02d:%02d", minutes, seconds));
updateSeekBar();
} else if (mediaPlayer == null && fromUser) {
prepareMediaPlayerFromPoint(progress);
updateSeekBar();
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (mediaPlayer != null) {
// remove message Handler from updating progress bar
handler.removeCallbacks(playRunnable);
}
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mediaPlayer != null) {
handler.removeCallbacks(playRunnable);
mediaPlayer.seekTo(seekBar.getProgress());
long minutes = TimeUnit.MILLISECONDS.toMinutes(mediaPlayer.getCurrentPosition());
long seconds = TimeUnit.MILLISECONDS.toSeconds(mediaPlayer.getCurrentPosition())
- TimeUnit.MINUTES.toSeconds(minutes);
startTime.setText(String.format("%02d:%02d", minutes, seconds));
updateSeekBar();
}
}
};
private void prepareMediaPlayerFromPoint(int progresss) {
mediaPlayer = new MediaPlayer();
try {
Uri uri = Uri.fromFile(new File(media.getUrl_file()));
String path = FileHelper.getPath(getActivity(), uri);
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
progress.setMax(mediaPlayer.getDuration());
mediaPlayer.seekTo(progresss);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
}
});
} catch (IOException e) {
}
}
public void loadNewMedia(FileModel media) {
this.media = media;
stopCompletely();
switchRecordingStatus(PLAYER_STATUS);
}
public boolean isStopped() {
return playbackStatus == STOPPED_STATUS;
}
public boolean isPlayView(View play) {
return this.play != null && this.play.equals(play);
}
public View.OnClickListener onPlayClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
togglePlayback();
}
};
public void setupObjects() {
handler = new Handler();
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
stopCompletely();
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(playRunnable);
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
public Runnable playRunnable = new Runnable() {
#Override
public void run() {
if (mediaPlayer != null) {
int mCurrentPosition = mediaPlayer.getCurrentPosition();
progress.setProgress(mCurrentPosition);
long minutes = TimeUnit.MILLISECONDS.toMinutes(mCurrentPosition);
long seconds = TimeUnit.MILLISECONDS.toSeconds(mCurrentPosition)
- TimeUnit.MINUTES.toSeconds(minutes);
startTime.setText(String.format("%02d:%02d", minutes, seconds));
updateSeekBar();
}
}
};
private void updateSeekBar() {
handler.postDelayed(playRunnable, 100);
}
public void stopCompletely() {
handler.removeCallbacks(playRunnable);
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
public void stopp() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
public void switchRecordingStatus(int status) {
if (cancel != null) cancel.setText("cancel");
recordingStatus = status;
switch (status) {
case READY_STATUS:
timer.cancel();
play.setVisibility(View.VISIBLE);
prepareToPlay();
if (mainAction != null) mainAction.setText("Play");
break;
case PLAYER_STATUS:
if (mainAction != null) mainAction.setVisibility(View.GONE);
switchPlaybackStatus(PLAYING_STATUS);
loadAudio();
}
}
public void prepareToPlay() {
switchPlaybackStatus(PAUSED_STATUS);
progress.setProgress(0);
progress.setMax(mediaPlayer.getDuration());
startTime.setText(TimeFormatter.getDurationString(0));
if (endTime != null) {
if (mediaPlayer != null)
endTime.setText(TimeFormatter.getDurationStringFromMillis(mediaPlayer.getDuration()));
else
endTime.setText(TimeFormatter.getDurationString(duration));
}
}
public void switchPlaybackStatus(int status) {
if (play == null) return;
playbackStatus = status;
play.setVisibility(View.VISIBLE);
switch (status) {
case PLAYING_STATUS:
play.setImageResource(R.drawable.ic_media_pause);
break;
case PAUSED_STATUS:
play.setImageResource(R.drawable.ic_play_arrow_blue_36dp);
break;
case STOPPED_STATUS:
play.setImageResource(R.drawable.ic_play_arrow_blue_36dp);
progress.setProgress(0);
}
}
public void togglePlayback() {
switch (playbackStatus) {
case PLAYING_STATUS:
mediaPlayer.pause();
switchPlaybackStatus(PAUSED_STATUS);
break;
case STOPPED_STATUS:
case PAUSED_STATUS:
loadAudio();
switchPlaybackStatus(PLAYING_STATUS);
}
}
public void loadAudio() {
if (mediaPlayer != null) {
play.setImageResource(R.drawable.ic_media_pause);
handler.removeCallbacks(playRunnable);
mediaPlayer.start();
updateSeekBar();
} else {
mediaPlayer = new MediaPlayer();
try {
if (recordingStatus == PLAYER_STATUS) {
Uri uri = Uri.fromFile(new File(media.getUrl_file()));
String path = FileHelper.getPath(getActivity(), uri);
mediaPlayer.setDataSource(path);
} else
mediaPlayer.setDataSource(recordedAudio.getAbsolutePath());
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepareAsync();
progress.setMax(mediaPlayer.getDuration());
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
startPlay();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if(mp.getCurrentPosition()!=0) {
resetPlayback();
switchPlaybackStatus(STOPPED_STATUS);
stopp();
}
}
});
} catch (IOException exception) {
Log.e(TAG, "prepare() failed");
}
}
}
public void startPlay() {
startTime.setText(TimeFormatter.getDurationString(0));
if (endTime != null) {
endTime.setText(TimeFormatter.getDurationStringFromMillis(mediaPlayer.getDuration()));
}
progress.setMax(mediaPlayer.getDuration());
loadingContainer.setVisibility(View.GONE);
handler.post(playRunnable);
mediaPlayer.start();
}
public void resetPlayback() {
if (handler != null) handler.removeCallbacks(playRunnable);
switchPlaybackStatus(STOPPED_STATUS);
play = null;
duration = 0;
progress = null;
if (mediaPlayer != null) {
startTime.setText(TimeFormatter.getDurationStringFromMillis(mediaPlayer.getDuration()));
}
}
public FileModel getCurrentMedia() {
return media;
}
}

Android mediaplayer play in background

I am working on mediaplayer app, but i have problem with onDestroy methods, i need to continue with playing music when i minimalize the app. But when i do it stops playing and throws errors or when i comment it, it is playing in background but problem is that it doesnt stop even when i kill the app, i can controll it just with my notification controller, but when i destroy controller by swiping, it is playing and i have music in background without music player.
public class MainActivity extends AppCompatActivity {
private MediaPlayerService player;
private boolean serviceBound = false;
private ArrayList<Audio> audioList;
private RWAdapter rwa;
private RecyclerView rv;
public static final String Broadcast_PLAY_NEW_AUDIO = "com.example.rsabo.mp3player.PlayNewAudio";
public static final String Broadcast_PAUSE_AUDIO= "com.example.rsabo.mp3player.PauseAudio";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
loadAudio();
initRW();
}
private void initRW(){
if (audioList.size()>0) {
rv = (RecyclerView) findViewById(R.id.myRecyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
;
rwa = new RWAdapter(audioList, getApplicationContext());
rv.setAdapter(rwa);
rv.addOnItemTouchListener(new MyTouchListener(this, new onItemClickListener() {
#Override
public void onClick(View view, int index) {
playAudio(index);
}
}));
}
}
//ulozi sa instancia
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("ServiceState", serviceBound);
}
//obnovi sa instancia tam kde bola naposledy ulozena
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
serviceBound = savedInstanceState.getBoolean("ServiceState");
}
//znici instanciu
#Override
protected void onDestroy() {
super.onDestroy();
// if(serviceBound){
// unbindService(serviceConnection);
// player.stopSelf();
// }
}
//viaze tuto triedu s prehravacom, nastavi hodnotu serviceBound na true ked sa vytvori spojenie
private ServiceConnection serviceConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
player = binder.getService();
serviceBound = true;
Toast.makeText(MainActivity.this, "Service bound", Toast.LENGTH_SHORT).show();
}
#Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
//Metoda pozrie ci je sluzba aktivna,
//ak nie je, do uloziska hodi arraylist s pesnickami, a spusti sluzbu
//ak je vlozi do uloziska novy audioIndex a posle spravu ze ma spustit pesnicku
private void playAudio(int audioIndex){
if(!serviceBound){
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
ulozisko.storeAudio(audioList);
ulozisko.storeAudioIndex(audioIndex);
Intent playerIntent = new Intent(this, MediaPlayerService.class);
startService(playerIntent);
bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} else {
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
ulozisko.storeAudioIndex(audioIndex);
Intent broadcastIntent = new Intent(Broadcast_PLAY_NEW_AUDIO);
sendBroadcast(broadcastIntent);
}
}
private void pauseAudio(){
Intent broadcastIntent = new Intent(Broadcast_PAUSE_AUDIO);
sendBroadcast(broadcastIntent);
}
//nacita pesnicky z mobilu
private void loadAudio() {
ContentResolver contentResolver = getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri, null, selection, null, sortOrder);
if(cursor != null && cursor.getCount() > 0) {
audioList = new ArrayList<>();
while (cursor.moveToNext()){
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
audioList.add(new Audio(data, title, album, artist));
}
}
cursor.close();
}
}
MediaPlayerService
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
private static final int NOTIFICATION_ID = 101;
private MediaSessionManager mediaSessionManager;
private MediaSessionCompat mediaSession;
private MediaControllerCompat.TransportControls transportControls;
private MediaPlayer mediaPlayer;
private String mediaFile;
private int resumePosition;
private AudioManager audioManager;
private boolean hovor = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private ArrayList<Audio> audioList;
private int audioIndex = -1;
private Audio activeAudio;
private final IBinder iBinder = new LocalBinder();
private PlayStatus status;
public static final String ACTION_PLAY = "com.example.rsabo.mp3player.ACTION_PLAY";
public static final String ACTION_PAUSE = "com.example.rsabo.mp3player.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "com.example.rsabo.mp3player.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "com.example.rsabo.mp3player.ACTION_NEXT";
public static final String ACTION_STOP = "com.example.rsabo.mp3player.ACTION_STOP";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return iBinder;
}
//pri vytvoreni zavola metody callStateListener(),registerJeNahlasReciever(), registerPlayNewAudio()
#Override
public void onCreate() {
super.onCreate();
callStateListener();
registerJeNahlasReciever();
registerPlayNewAudio();
}
//podla priority zvuku v systeme zvysi zvuk, ukonci, zastavi alebo stisi mediaPlayer
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
//metoda na ziskanie AudioFocusu/priority hrania zvuku
private boolean requestAudioFocus() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
//metoda ktora odstrani audioFocus
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == audioManager.abandonAudioFocus(this);
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
}
#Override
public void onCompletion(MediaPlayer mp) {
skipToNext();
buildNotification(PlayStatus.PLAYING);
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Log.d("Media Player error", "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK" + extra);
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.d("Media Player error", "MEDIA_ERROR_SERVER_DIED" + extra);
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.d("Media Player error", "MEDIA_ERROR_UNKNOWN" + extra);
break;
}
return false;
}
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
#Override
public void onSeekComplete(MediaPlayer mp) {
}
class LocalBinder extends Binder {
MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
//inicializacia mediaPlayeru, ak sa nenastavi cesta vyhodi chybu a zastavi sa
private void initMediaPlayer() {
if (mediaPlayer == null)
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
// nastavi cestu k hudbe
mediaPlayer.setDataSource(activeAudio.getData());
} catch (IOException e) {
e.printStackTrace();
stopSelf();
}
mediaPlayer.prepareAsync();
}
//nastavenie funkcie tlacidla play
private void playMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
//nastavenie funkcie tlacidla stop
private void stopMedia() {
if (mediaPlayer == null) return;
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
//nastavenie funkcie tlacidla pause
private void pauseMedia() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
resumePosition = mediaPlayer.getCurrentPosition();
}
}
//nastavenie funkcie tlacidla resume
private void resumeMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
}
}
//inicializuje prhravac, ak neziska audiofocus alebo cestu k hudbe zastavi sa
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
audioList = ulozisko.loadAudio();
audioIndex = ulozisko.loadAudioIndex();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
} catch (NullPointerException e) {
stopSelf();
}
if (!requestAudioFocus()) {
stopSelf();
}
if (mediaSessionManager == null) {
try {
initMediaSession();
initMediaPlayer();
} catch (RemoteException e) {
e.printStackTrace();
stopSelf();
}
buildNotification(PlayStatus.PLAYING);
}
handleIncomingActions(intent);
return super.onStartCommand(intent, flags, startId);
}
//metode prida zrusenie audiofocusu a nastavi prehravac na null, vypne phoneStateListener, odregistruje recievre, zmaze notifikaciu a vycisti playlist
#Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
stopMedia();
mediaPlayer.release();
}
removeAudioFocus();
if (phoneStateListener != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
removeNotification();
unregisterReceiver(jeNahlasReciever);
unregisterReceiver(playNewAudio);
new Ulozisko(getApplicationContext()).clearCacheAudioPlaylist();
}
//ked sa vyberu sluchadla tak sa hranie zastavi
private BroadcastReceiver jeNahlasReciever = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
pauseMedia();
buildNotification(PlayStatus.PAUSED);
}
};
private void registerJeNahlasReciever() {
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(jeNahlasReciever, intentFilter);
}
//metoda ktora zisiti v akom stave je hovor, a ked telefon zvoni alebo prebieha hovor, zastavi prehravanie
private void callStateListener() {
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseMedia();
hovor = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (mediaPlayer != null) {
if (hovor) {
hovor = false;
resumeMedia();
}
}
break;
}
}
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
//ked prepnem pesnicku tak sa pomocou tejto metody resetne prehravac a prepne na dalsiu pesnicku podla indexu ktory dostala v sprave
private BroadcastReceiver playNewAudio = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// if(status == PlayStatus.PAUSED) {
audioIndex = new Ulozisko(getApplicationContext()).loadAudioIndex();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
updateInfo();
buildNotification(PlayStatus.PLAYING);
// } else if (status == PlayStatus.PLAYING){
// pauseMedia();
// updateInfo();
// buildNotification(PlayStatus.PAUSED);
// }
}
};
private void registerPlayNewAudio() {
IntentFilter filter = new IntentFilter(MainActivity.Broadcast_PLAY_NEW_AUDIO);
registerReceiver(playNewAudio, filter);
}
//skontroluje ci mediaSessionManager existuje
//vytvori mediaSession a da mu controller
private void initMediaSession() throws RemoteException {
if (mediaSessionManager != null) return;
mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
mediaSession = new MediaSessionCompat(getApplicationContext(), "Prehravac");
transportControls = mediaSession.getController().getTransportControls();
mediaSession.setActive(true);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
updateInfo();
mediaSession.setCallback(new MediaSessionCompat.Callback() {
#Override
public void onPlay() {
super.onPlay();
resumeMedia();
buildNotification(PlayStatus.PLAYING);
}
#Override
public void onPause() {
super.onPause();
pauseMedia();
buildNotification(PlayStatus.PAUSED);
}
#Override
public void onSkipToNext() {
super.onSkipToNext();
skipToNext();
updateInfo();
buildNotification(PlayStatus.PLAYING);
}
#Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
skipToPrevious();
updateInfo();
buildNotification(PlayStatus.PLAYING);
}
#Override
public void onStop() {
super.onStop();
removeNotification();
stopSelf();
}
#Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
}
});
}
//updatne aktualne info o pesnicke
private void updateInfo() {
Bitmap albumArt = BitmapFactory.decodeResource(getResources(), R.drawable.image);
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
//.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, activeAudio.getArtist())
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, activeAudio.getAlbum())
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, activeAudio.getTitle())
.build());
}
//metoda ktora prepne pesnicku na dalsiu, ak je pesnicka posledna tak ju nastavi na prvu v zozname
private void skipToNext() {
if (audioIndex == audioList.size() - 1) {
audioIndex = 0;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(++audioIndex);
}
new Ulozisko(getApplicationContext()).storeAudioIndex(audioIndex);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
//metoda ktora prepne pesnicku dozadu, ak je na zaciatku zoznamu tak ju nastavi na poslednu
private void skipToPrevious() {
if (audioIndex == 0) {
audioIndex = audioList.size() - 1;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(--audioIndex);
}
new Ulozisko(getApplicationContext()).storeAudioIndex(audioIndex);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
//metoda ktora spravi v notifikacnom panely prehravac a vzdy ked sa vola tato metoda tak sa v notifikacii updatne info o pesnicke
private void buildNotification(PlayStatus playStatus) {
int notificationAction = android.R.drawable.ic_media_pause;
PendingIntent playAleboPause = null;
if (playStatus == PlayStatus.PLAYING) {
notificationAction = android.R.drawable.ic_media_pause;
playAleboPause = playbackAction(1);
status = PlayStatus.PLAYING;
} else if (playStatus == PlayStatus.PAUSED) {
notificationAction = android.R.drawable.ic_media_play;
playAleboPause = playbackAction(0);
status = PlayStatus.PAUSED;
}
Bitmap albumArt = BitmapFactory.decodeResource(getResources(), R.drawable.image);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setShowWhen(false)
.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(mediaSession.getSessionToken())
.setShowActionsInCompactView(0, 1, 2))
.setColor(getResources().getColor(R.color.colorPrimary))
//.setLargeIcon(activeAudio.)
.setSmallIcon(android.R.drawable.stat_sys_headset)
.setContentText(activeAudio.getArtist())
.setContentTitle(activeAudio.getTitle())
.setSubText(activeAudio.getAlbum())
.addAction(android.R.drawable.ic_media_previous, "previous", playbackAction(3))
.addAction(notificationAction, "pause", playAleboPause)
.addAction(ic_media_next, "next", playbackAction(2));
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
}
//zmaze notifikaciu
private void removeNotification() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
// nastavenie akcie na tlacidla v notifikacii
private PendingIntent playbackAction(int cisloAkcie) {
Intent akcia = new Intent(this, MediaPlayerService.class);
switch (cisloAkcie) {
case 0:
akcia.setAction(ACTION_PLAY);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 1:
akcia.setAction(ACTION_PAUSE);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 2:
akcia.setAction(ACTION_NEXT);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 3:
akcia.setAction(ACTION_PREVIOUS);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
default:
break;
}
return null;
}
//metoda zisti ktora akcia je aktualna a zavola metodu cez transportControls
private void handleIncomingActions(Intent playbackAction) {
if (playbackAction == null || playbackAction.getAction() == null) return;
String akcia = playbackAction.getAction();
if (akcia.equalsIgnoreCase(ACTION_PLAY)) {
transportControls.play();
} else if (akcia.equalsIgnoreCase(ACTION_PAUSE)) {
transportControls.pause();
} else if (akcia.equalsIgnoreCase(ACTION_NEXT)) {
transportControls.skipToNext();
} else if (akcia.equalsIgnoreCase(ACTION_PREVIOUS)) {
transportControls.skipToPrevious();
} else if (akcia.equalsIgnoreCase(ACTION_STOP)) {
transportControls.stop();
}
}
}
Try this to startForeground()
Notification.Builder mBuilder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_icon)
.setContentTitle(getString(R.string.title))
.setContentText("");
Intent resultIntent = new Intent(this, ResultIntent.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ParentStack.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int mId = 1489;
startForeground(mId, mBuilder.build());

Android - SeekBar and MediaPlayer

I needed to connect my SeekBar with my MediaPlayer in my App.
I set up the SeekBar via xml like this:
<SeekBar
android:id="#+id/song_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"/>
and followed this SO answer to implement it.
This is my code:
public class Song_main extends AppCompatActivity {
private final int SONG_REQUEST_CODE = 1;
private Uri song;
private TextView selectSong;
private SeekBar seekBar;
private Handler handler;
private MediaPlayer mediaPlayer;
private boolean repeatPressedTwice = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_bar_song_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.song_main_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
seekBar = (SeekBar) findViewById(R.id.song_seekbar);
handler = new Handler();
notSelected();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.song, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.song_plus) {
Intent selectIntent = new Intent(Intent.ACTION_GET_CONTENT);
selectIntent.setType("audio/*");
startActivityForResult(selectIntent, SONG_REQUEST_CODE);
}
return true;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SONG_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if ((data != null) && (data.getData()!=null)) {
song = data.getData();
setup();
}
}
}
private void notSelected() {
selectSong = (TextView) findViewById(R.id.select_song_textview);
selectSong.setText(getResources().getString(R.string.song_not_selected));
}
public void onPlayButtonClicked(View v) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
pb.setImageResource(R.drawable.pause);
updateSeekBar();
} else {
mediaPlayer.pause();
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}
public void onControlsClicked(View v) {
if (v.getId() == R.id.fast_forward) {
int pos = mediaPlayer.getCurrentPosition();
pos += 1500;
mediaPlayer.seekTo(pos);
}
else if (v.getId() == R.id.fast_backward) {
int pos = mediaPlayer.getCurrentPosition();
pos -= 1500;
mediaPlayer.seekTo(pos);
}
else if (v.getId() == R.id.skip_backward) {
mediaPlayer.seekTo(0);
}
}
public void onRepeatClicked(View v) {
if (!repeatPressedTwice) {
// TODO: change visual color of repeat button
mediaPlayer.setLooping(true);
Toast.makeText(this, "repeat enabled", Toast.LENGTH_SHORT).show();
repeatPressedTwice = true;
} else {
mediaPlayer.setLooping(false);
}
}
private void setup() {
/* the song has been select setup the interface */
/* displays song name in title */
TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
String songName;
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(song, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
titleView.setText(songName);
}
/* removes the notSelected String */
selectSong.setVisibility(View.GONE);
/* setup media player */
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), song);
mediaPlayer.prepareAsync();
} catch (IOException e) {
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
/* show media player layout */
RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
mpl.setVisibility(View.VISIBLE);
mediaPlayer.start();
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.pause);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
});
seekBar = (SeekBar) findViewById(R.id.song_seekbar);
seekBar.setMax(mediaPlayer.getDuration());
updateSeekBar();
}
private void updateSeekBar() {
seekBar.setProgress(mediaPlayer.getCurrentPosition()/1000);
handler.postDelayed(runnable, 1000);
}
Runnable runnable = new Runnable() {
#Override
public void run() {
updateSeekBar();
}
};
#Override
public void onStop() {
super.onStop();
if (mediaPlayer!=null)
mediaPlayer.stop();
}
}
The process starts from the onOptionsItemSelected method.
The seekBar behaves correctly, it increments every second. The problem now is that it finishes way before the song finishes.
I tried adding
seekBar.setMax(mediaPlayer.getDuration());
in the setup method, but that causes the bar not to move at all.
You need to define separate Runnable and trigger it every x miliseconds (depends on you) once MediaPlayer starts.
Define a function updateSeekbar like,
private void updateSeekBar() {
audioSeek.setProgress(player.getCurrentPosition());
txtCurrentTime.setText(milliSecondsToTimer(player.getCurrentPosition()));
seekHandler.postDelayed(runnable, 50);
}
And Runnable
Runnable runnable = new Runnable() {
#Override
public void run() {
updateSeekBar();
}
};
Now you just have to call updateSeekbar once when playing starts. In your case:
public void onPlayButtonClicked(View v) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
pb.setImageResource(R.drawable.pause);
updateSeekBar();
} else {
mediaPlayer.pause();
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}
FYI
Function milliSecondsToTimer works as follows
private String milliSecondsToTimer(long milliseconds) {
String finalTimerString = "";
String secondsString = "";
// Convert total duration into time
int hours = (int) (milliseconds / (1000 * 60 * 60));
int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);
// Add hours if there
if (hours > 0) {
finalTimerString = hours + ":";
}
// Prepending 0 to seconds if it is one digit
if (seconds < 10) {
secondsString = "0" + seconds;
} else {
secondsString = "" + seconds;
}
finalTimerString = finalTimerString + minutes + ":" + secondsString;
// return timer string
return finalTimerString;
}
UPDATE
You have called setMax at the wrong place. Update setup() function as follows
private void setup() {
/* the song has been select setup the interface */
/* displays song name in title */
TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
String songName;
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(song, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
titleView.setText(songName);
}
/* removes the notSelected String */
selectSong.setVisibility(View.GONE);
/* setup media player */
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), song);
mediaPlayer.prepareAsync();
} catch (IOException e) {
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
/* show media player layout */
seekBar.setMax(mediaPlayer.getDuration());
RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
mpl.setVisibility(View.VISIBLE);
mediaPlayer.start();
updateSeekBar();
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.pause);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
});
}
You have implement OnSeekBarChangeListener and in onCreate() add the below line:-
seekBar = (SeekBar) findViewById(R.id.seekBar);
And override the onProgressChanged() method , in this method you can set the progress in the seekbar using the below line:
mPlayer.seekTo(progress);
seekBar.setProgress(progress);
or
After you initialise your MediaPlayer and for example press the play button, you should create an handler and post runnable so you can update your SeekBar (in the UI thread itself) with the current position of your MediaPlayer like this :
private Handler mHandler = new Handler();
//Make sure you update Seekbar on UI thread
MainActivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
if(mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
and update that value every second.
If you need to update the MediaPlayer's position while user drag your SeekBar you should add OnSeekBarChangeListener to your SeekBar and do it there :
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mMediaPlayer != null && fromUser){
mMediaPlayer.seekTo(progress * 1000);
}
}
});
you need to update your Seek bar when you play a song
public void updateProgressBar() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mHandler.postDelayed(mUpdateTimeTask, 100);
}
});
}
Below Runnable method to update seekbar
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
if (MusicService.isRunning()) {
duration = MusicService.getDur();
long currSongPosition = MusicService.getPosn();
totTime.setText(Utility.milliSecondsToTimer(duration));
fromTime.setText(Utility.milliSecondsToTimer(currSongPosition));
int progress = Utility.getProgressPercentage(currSongPosition, duration);
songProgressBar.setProgress(progress);
updateProgressBar();
}
}
};
Using this below function you can get progress percentage from song current position and song duration
public static int getProgressPercentage(long currentDuration, long totalDuration) {
Double percentage;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
percentage = (((double) currentSeconds) / totalSeconds) * 100;
return percentage.intValue();
}

Categories