0

I have an AudioActivity that uses RecyclerView to show list of audio that is to be streamed. When I press back to go to MainActivity and open AudioActiviy again, the SeekBar and the timer for the audio is reset but the music is still playing. I don't want the seekBar to reset but continue from where the music is playing.

Minimizing the app while the music is playing(from AudioActivity when seekBar is also updating) and opening it again gives the required effect as the seekbar continues from the position of the music.Is there any way mimic this effect when going back from an activity and opening it again?

Code for Activity is:

public class AudioActivity extends AppCompatActivity {
RecyclerView rvAudio;

@Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initialize();

}


private void initialize() {
    rvAudio =(RecyclerView) findViewById(R.id.rv_audio);
    rvAudio.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
    final AudioAdapter audioAdapter = new AudioAdapter(AudioActivity.this,getData());
    rvAudio.setAdapter(audioAdapter);
    rvAudio.setLayoutManager(new LinearLayoutManager(this));
}

public static ArrayList<AudioModel> getData(){
    ArrayList<AudioModel> list = new ArrayList<>();
    String[] audioName = {"Audio one","Audio two","Audio Three"};
    String[] url ={"https://www.mfiles.co.uk/mp3-downloads/silent-night.mp3","https://www.mfiles.co.uk/mp3-downloads/silent-night.mp3","https://www.mfiles.co.uk/mp3-downloads/silent-night.mp3"};
    for (int i=0; i<url.length; i++){
        AudioModel data = new AudioModel();
        data.url= url[i];
        data.name = audioName[i];
        list.add(data);
    }
    return list;
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    Intent intent = new Intent(this, MainActivity.class);
    startActivity(intent);
}
}

Code for Adapter:

public class AudioAdapter extends RecyclerView.Adapter<AudioAdapter.ViewHolder> {
Context context;
LayoutInflater inflator;
ArrayList<AudioModel> list = new ArrayList();
Handler seekHandler = new Handler();
Runnable run;

public AudioAdapter(Context context, ArrayList<AudioModel> list) {
    this.context = context;
    this.list = list;
    inflator = LayoutInflater.from(context);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = inflator.inflate(R.layout.audio_recyclerview_layout, parent, false);
    AudioAdapter.ViewHolder viewHolder = new AudioAdapter.ViewHolder(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {

    final AudioModel modelList = list.get(position);
    holder.tvAudioName.setText(modelList.name);

    // Initializing MediaPlayer
    final MediaPlayer mediaPlayer = new MediaPlayer();

    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    try {
        mediaPlayer.setDataSource(modelList.url);
        mediaPlayer.prepare();// might take long for buffering.
    } catch (IOException e) {
        e.printStackTrace();
    }

    holder.seekBar.setMax(mediaPlayer.getDuration());
    holder.seekBar.setTag(position);
    //run.run();
    holder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (mediaPlayer != null && fromUser) {
                mediaPlayer.seekTo(progress);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
    holder.tvAudioLength.setText("0:00/"+calculateDuration(mediaPlayer.getDuration()));
    holder.btn_play.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (!mediaPlayer.isPlaying()) {
                mediaPlayer.start();
                holder.btn_play.setText("Pause");
                 run = new Runnable() {
                    @Override
                    public void run() {
                        // Updateing SeekBar every 100 miliseconds
                        holder.seekBar.setProgress(mediaPlayer.getCurrentPosition());
                        seekHandler.postDelayed(run, 100);
                        //For Showing time of audio(inside runnable)
                        int miliSeconds = mediaPlayer.getCurrentPosition();
                        if(miliSeconds!=0) {
                            //if audio is playing, showing current time;
                            long minutes = TimeUnit.MILLISECONDS.toMinutes(miliSeconds);
                            long seconds = TimeUnit.MILLISECONDS.toSeconds(miliSeconds);
                            if (minutes == 0) {
                               holder.tvAudioLength.setText("0:" + seconds + "/" +calculateDuration(mediaPlayer.getDuration()));
                            } else {
                                if (seconds >= 60) {
                                    long sec = seconds - (minutes * 60);
                                    holder.tvAudioLength.setText(minutes + ":" + sec+ "/" +calculateDuration(mediaPlayer.getDuration()));
                                }
                            }
                        }else{
                            //Displaying total time if audio not playing
                            int totalTime=mediaPlayer.getDuration();
                            long minutes = TimeUnit.MILLISECONDS.toMinutes(totalTime);
                            long seconds = TimeUnit.MILLISECONDS.toSeconds(totalTime);
                            if (minutes == 0) {
                                holder.tvAudioLength.setText("0:" + seconds);
                            } else {
                                if (seconds >= 60) {
                                    long sec = seconds - (minutes * 60);
                                    holder.tvAudioLength.setText(minutes + ":" + sec);
                                }
                            }
                        }
                    }

                };
                run.run();
            } else {
                mediaPlayer.pause();
                holder.btn_play.setText("Play");
            }
        }
    });
}

@Override
public int getItemCount() {
    return list.size();
}

class ViewHolder extends RecyclerView.ViewHolder {
    Button btn_play;
    TextView tvAudioLength;
    TextView tvAudioName;
    SeekBar seekBar;

    public ViewHolder(View itemView) {
        super(itemView);
       // mTvAudioLength =(TextView) itemView.findViewById(R.id.tv_audio_lenght);
       // mSeekBar = (SeekBar) itemView.findViewById(R.id.seekBar);
        btn_play = (Button) itemView.findViewById(R.id.btn_play);
        tvAudioLength = (TextView) itemView.findViewById(R.id.tv_audio_lenght);
        tvAudioName = (TextView) itemView.findViewById(R.id.tv_audio_name);
        seekBar = (SeekBar) itemView.findViewById(R.id.seekBar);

    }
}

private String calculateDuration(int duration) {
    String finalDuration = "";
    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration);
    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration);
    if (minutes == 0) {
        finalDuration = "0:" + seconds;
    } else {
        if (seconds >= 60) {
            long sec = seconds - (minutes * 60);
            finalDuration = minutes + ":" + sec;
        }
    }
    return finalDuration;
}

}

RecyclerView Item Layout:

 <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context="com.example.aditya.audio.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10dp"
        android:paddingLeft="10dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_audio_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingRight="10dp"
            android:text="Audio Name"
            android:textColor="#000000"
            android:textSize="18dp"
            android:paddingTop="5dp" />
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
        <SeekBar android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="10dp"
            android:layout_weight="1"
            android:id="@+id/seekBar"
            android:layout_marginRight="5dp"
            android:text="Duration"/>
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
    android:layout_weight="0"
        android:id="@+id/tv_audio_lenght"
        android:paddingRight="15dp"
        android:text="0:00"/>
</LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_gravity="center"
        android:layout_weight="0"
        android:orientation="horizontal"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="0dp">

        <Button
            android:id="@+id/btn_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="0dp"
            android:text="Play" />

    </LinearLayout>
</LinearLayout>

AudioActivity layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.aditya.audio.MainActivity">
<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rv_audio"
    />
</LinearLayout>
AD.
  • 329
  • 1
  • 3
  • 10

1 Answers1

0

If you want to keep tracking of currently playing music and show in view when you re-visit the application, you can get currently playing position and seek to that position in seekbar, like this:

 length=mediaplayer.getCurrentPosition();
 mediaplayer.seekTo(length);

But this is not the best practice. It would be wise if you implement the background service which plays the music and tracks of all the playing information like:

  1. Funkytunes
  2. Google sample music player

Also audioactivity takes long time to open because of UI thread operation for long time in audioadapter. What happens when your music list grows to 20, 50,100, I think your app might crash.
So it would be best if you implement the background service and playback manager like in above application.

When I press back to go to MainActivity and open AudioActiviy again, the SeekBar and the timer for the audio is reset but the music is still playing.

  • Because going back to previous activity destroys audio activity view, and reset the view.

Minimizing the app while the music is playing(from AudioActivity when seekBar is also updating) and opening it again gives the required effect as the seekbar continues from the position of the music.

  • This is because your app is in background and views not destroyed yet.
captaindroid
  • 2,868
  • 6
  • 31
  • 45
  • hmm...ok...I will try implementing service, but is it possible not to destroy the view when back is pressed(and have the same effect as minimizing)? – AD. Nov 21 '17 at 08:45
  • You can save the android activity/fragment state using [SaveInstanceState](https://stackoverflow.com/questions/151777/saving-android-activity-state-using-save-instance-state) but it's not exactly same as what you are referring to. – captaindroid Nov 21 '17 at 10:58