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();
}
Related
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);
}
}
}
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.
My SeekBar can work but then it can't auto-run the SeekBar progress
when I clicked on the SeekBar I will auto move to the position with an overlay player. and the runnable thread does not on the SeekBar
the line below is the code of my SeekBar
positionBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser && progress != 100) {
player.getDuration();
player.seekTo(progress);
positionBar.setProgress(progress);
Toast.makeText(getApplicationContext(), "seekbar progress: " + progress, Toast.LENGTH_SHORT).show();
}else {
progress = 0;
positionBar.setProgress(progress);
Song nextSong = songCollection.getNextSong(songId);
if(nextSong != null){
songId = nextSong.getId();
title = nextSong.getTitle();
artist = nextSong.getArtist();
fileLink = nextSong.getFileLink();
coverArt = nextSong.getCoverArt();
url = BASE_URL + fileLink;
displaySong(title,artist,coverArt);
stopActivities();
}
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//
Toast.makeText(getApplicationContext(),"seekbar touch started!", Toast.LENGTH_SHORT).show();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// player.seekTo(musicPostion);
Toast.makeText(getApplicationContext(),"seekbar touch stop!", Toast.LENGTH_SHORT).show();
}
}
);
new Thread(new Runnable() {
#Override
public void run() {
while(player != null){
try{
Message msg = new Message();
msg.what = player.getCurrentPosition();
handler.sendMessage(msg);
positionBar.setProgress(player.getCurrentPosition());
Thread.sleep(1000);
}catch (InterruptedException e){
}
}
}
}).start();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
int currentPosition = msg.what;
positionBar.setProgress(currentPosition);
}
};`
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.
I'm playing sound in android audio player activity. when i pause that activity, the sound keep on playing in background. I want to stop that sound when i resume that audio player activity.
here is my code..
can anyone help how i could do this.any help would be much appreciated, thank you :)
public class AndroidBuildingMusicPlayerActivity extends Activity implements
OnCompletionListener, SeekBar.OnSeekBarChangeListener {
private ImageButton btnPlay;
private ImageButton btnForward;
private ImageButton btnBackward;
// private ImageButton btnNext;
// private ImageButton btnPrevious;
// private ImageButton btnPrevious;
private ImageButton btnPlaylist;
private ImageView songimg;
// private ImageButton btnRepeat;
// private ImageButton btnShuffle;
private SeekBar songProgressBar;
private TextView songTitleLabel;
private TextView songCurrentDurationLabel;
private TextView songTotalDurationLabel;
// Media Player
private MediaPlayer mp;
// Handler to update UI timer, progress bar etc,.
private Handler mHandler = new Handler();;
private SongsManager songManager;
private Utilities utils;
private int seekForwardTime = 5000; // 5000 milliseconds
private int seekBackwardTime = 5000; // 5000 milliseconds
private int currentSongIndex = 0;
private boolean isShuffle = false;
private boolean isRepeat = false;
private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
String[] stringArray = new String[4];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mediaplayer);
// All player buttons
btnPlay = (ImageButton) findViewById(R.id.btnPlay);
btnForward = (ImageButton) findViewById(R.id.btnForward);
btnBackward = (ImageButton) findViewById(R.id.btnBackward);
// btnNext = (ImageButton) findViewById(R.id.btnNext);
// btnPrevious = (ImageButton) findViewById(R.id.btnPrevious);
btnPlaylist = (ImageButton) findViewById(R.id.btnPlaylist);
songimg = (ImageView) findViewById(R.id.songimg);
// btnShuffle = (ImageButton) findViewById(R.id.btnShuffle);
btnPlaylist = (ImageButton) findViewById(R.id.btnPlaylist);
songProgressBar = (SeekBar) findViewById(R.id.songProgressBar);
songTitleLabel = (TextView) findViewById(R.id.songTitle);
songCurrentDurationLabel = (TextView) findViewById(R.id.songCurrentDurationLabel);
songTotalDurationLabel = (TextView) findViewById(R.id.songTotalDurationLabel);
// Mediaplayer
mp = new MediaPlayer();
songManager = new SongsManager();
utils = new Utilities();
// Listeners
songProgressBar.setOnSeekBarChangeListener(this); // Important
mp.setOnCompletionListener(this); // Important
// Getting all songs list
songsList = songManager.getPlayList();
final String[] stringArray = getIntent().getStringArrayExtra("string-array");
// By default play first song
playSong(stringArray[0]);
songTitleLabel.setText(stringArray[1]);
new DownloadImageTask(songimg).execute(stringArray[2]);
btnPlaylist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
final String[] option = new String[] {"Share",
"Stop" };
ArrayAdapter<String> adapters = new ArrayAdapter<String>(
AndroidBuildingMusicPlayerActivity.this,
android.R.layout.select_dialog_item, option);
AlertDialog.Builder builder = new AlertDialog.Builder(
AndroidBuildingMusicPlayerActivity.this);
builder.setTitle("Choose Action");
builder.setAdapter(adapters,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
if (which == 1) {
mp.stop();
finish();
}
if (which == 0) {
Intent browserIntent = new Intent(
Intent.ACTION_SEND);
browserIntent.setType("text/plain");
browserIntent.putExtra(
android.content.Intent.EXTRA_TEXT,
stringArray[3]);
// ,
// Uri.parse("https://www.youtube.com/watch?v="+ids.get(mPosition)));
startActivity(Intent.createChooser(
browserIntent, "Share Song Link"));
}
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
});
/**
* Play button click event plays a song and changes button to pause
* image pauses a song and changes button to play image
* */
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// check for already playing
if (mp.isPlaying()) {
if (mp != null) {
mp.pause();
// Changing button image to play button
btnPlay.setImageResource(R.drawable.btn_play);
}
} else {
// Resume song
if (mp != null) {
mp.start();
// Changing button image to pause button
btnPlay.setImageResource(R.drawable.btn_pause);
}
}
}
});
/**
* Forward button click event Forwards song specified seconds
* */
btnForward.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// get current song position
int currentPosition = mp.getCurrentPosition();
// check if seekForward time is lesser than song duration
if (currentPosition + seekForwardTime <= mp.getDuration()) {
// forward song
mp.seekTo(currentPosition + seekForwardTime);
} else {
// forward to end position
mp.seekTo(mp.getDuration());
}
}
});
/**
* Backward button click event Backward song to specified seconds
* */
btnBackward.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// get current song position
int currentPosition = mp.getCurrentPosition();
// check if seekBackward time is greater than 0 sec
if (currentPosition - seekBackwardTime >= 0) {
// forward song
mp.seekTo(currentPosition - seekBackwardTime);
} else {
// backward to starting position
mp.seekTo(0);
}
}
});
}
/**
* Receiving song index from playlist view and play the song
* */
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 100) {
currentSongIndex = data.getExtras().getInt("songIndex");
// play selected song
playSong(stringArray[0]);
}
}
/**
* Function to play a song
*
* #param songIndex
* - index of song
* */
public void playSong(String songpath) {
// Play song
try {
mp.reset();
mp.setDataSource(songpath);
mp.prepare();
mp.start();
// Displaying Song title
// String songTitle = songsList.get(songIndex).get("songTitle");
// songTitleLabel.setText(songTitle);
// Changing Button Image to pause image
btnPlay.setImageResource(R.drawable.btn_pause);
// set Progress bar values
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
// Updating progress bar
updateProgressBar();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Update timer on seekbar
* */
public void updateProgressBar() {
mHandler.postDelayed(mUpdateTimeTask, 100);
}
/**
* Background Runnable thread
* */
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
long totalDuration = mp.getDuration();
long currentDuration = mp.getCurrentPosition();
// Displaying Total Duration time
songTotalDurationLabel.setText(""
+ utils.milliSecondsToTimer(totalDuration));
// Displaying time completed playing
songCurrentDurationLabel.setText(""
+ utils.milliSecondsToTimer(currentDuration));
// Updating progress bar
int progress = (int) (utils.getProgressPercentage(currentDuration,
totalDuration));
// Log.d("Progress", ""+progress);
songProgressBar.setProgress(progress);
// Running this thread after 100 milliseconds
mHandler.postDelayed(this, 100);
}
};
/**
*
* */
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromTouch) {
}
/**
* When user starts moving the progress handler
* */
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// remove message Handler from updating progress bar
mHandler.removeCallbacks(mUpdateTimeTask);
}
/**
* When user stops moving the progress hanlder
* */
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mHandler.removeCallbacks(mUpdateTimeTask);
int totalDuration = mp.getDuration();
int currentPosition = utils.progressToTimer(seekBar.getProgress(),
totalDuration);
// forward or backward to certain seconds
mp.seekTo(currentPosition);
// update timer progress again
updateProgressBar();
}
/**
* On Song Playing completed if repeat is ON play same song again if shuffle
* is ON play random song
* */
#Override
public void onCompletion(MediaPlayer arg0) {
// check for repeat is ON or OFF
if (isRepeat) {
// repeat is on play same song again
playSong(stringArray[0]);
} else if (isShuffle) {
// shuffle is on - play a random song
Random rand = new Random();
currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
playSong(stringArray[0]);
} else {
// no repeat or shuffle ON - play next song
if (currentSongIndex < (songsList.size() - 1)) {
playSong(stringArray[0]);
currentSongIndex = currentSongIndex + 1;
} else {
// play first song
playSong(stringArray[0]);
currentSongIndex = 0;
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
//mp.stop();
}
class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
// pd.show();
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
// pd.dismiss();
bmImage.setImageBitmap(result);
}
}
}
Try: Override onStop() and onRestart()
#Override
protected void onStop() {
super.onStop();
if (mp.isPlaying()) {
mp.stop();
// or mp.pause();
}
}
#Override
public void onRestart() {
super.onRestart();
if (mp == null) {
//create mp from current song, for example
mp = MediaPlayer.create(AndroidBuildingMusicPlayerActivity.this, currentSong);
}
mp.start();
}
EDIT:
try:
#Override
protected void onPause() {
super.onPause();
try{
if (mp.isPlaying()) {
mp.pause();
}
}catch(Exception we){
we.printStackTrace();
}
}
#Override
protected void onResume() {
super.onResume();
try{
mp.start();
}catch(Exception we){
we.printStackTrace();
}
}
you should use AUDIO FOCUS and onfocuschangelistener it will solve your problem.