How can I control the media player with service?

Viewed 917

I am new to coding and at this point, I made a media player that starts and pauses the audio, has a working seekbar, duration, etc. Now I faced a big issue. The audio can't be played in the background and I found out that I can do this with service but this changes things. I read all kinds of topics on how to control the audio in service with seekbar and all kinds of stuff but nothing helped me. The main problem I face is having the seekbar to control the audio and a text to read the time. If there is someone to help me find a code for this it would be much appreciated.

The layout:

 <SeekBar
    android:id="@+id/seekBarMusic1"
    android:layout_width="match_parent"
    android:layout_height="@dimen/_20sdp"
    android:layout_marginTop="@dimen/_12sdp"
    android:layout_marginLeft="@dimen/_20sdp"
    android:layout_marginRight="@dimen/_20sdp"
    app:layout_constraintTop_toBottomOf="@+id/cardView"
    tools:layout_editor_absoluteX="10dp" />

<TextView
    android:id="@+id/playerPositionMusic"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="00:00"
    android:textColor="@color/remain_black"
    android:textSize="25dp"
    android:layout_marginBottom="@dimen/_80sdp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="@+id/cardView"
    app:layout_constraintTop_toBottomOf="@+id/seekBarMusic1" />

<TextView
    android:id="@+id/text_time"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="@dimen/_80sdp"
    android:text="15:00"
    android:textColor="@color/remain_black"
    android:textSize="25dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="@+id/cardView"
    app:layout_constraintTop_toBottomOf="@+id/seekBarMusic1" />

<ImageView
    android:id="@+id/btPlayMusic"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:alpha="0.9"
    android:background="@drawable/play"
    android:theme="@style/Button.White"
    app:layout_constraintEnd_toStartOf="@+id/text_time"
    app:layout_constraintStart_toEndOf="@+id/playerPositionMusic"
    app:layout_constraintTop_toBottomOf="@+id/seekBarMusic1"
    app:tint="@color/remain_black" />

 <ImageView
    android:visibility="gone"
    android:id="@+id/btPauseMusic"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:alpha="0.9"
    android:background="@drawable/pause"
    android:theme="@style/Button.White"
    app:layout_constraintEnd_toStartOf="@+id/text_time"
    app:layout_constraintStart_toEndOf="@+id/playerPositionMusic"
    app:layout_constraintTop_toBottomOf="@+id/seekBarMusic1"
    app:tint="@color/remain_black" />

The code I used before:

public class m1 extends AppCompatActivity {

ImageView btPlay, btPause;
TextView playerPosition, playerDuration;
CircularSeekBar seekBar;

MediaPlayer mediaPlayer;
Handler handler = new Handler();
Runnable runnable;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_m1);

    findViewById(R.id.backm1).setOnClickListener(v -> onBackPressed());

    playerPosition = findViewById(R.id.playerPosition);
    playerDuration = findViewById(R.id.playerDuration);
    replay = findViewById(R.id.replay);
    forward = findViewById(R.id.forward);
    seekBar = findViewById(R.id.seekBar);
    btPause = findViewById(R.id.btPause);
    btPlay = findViewById(R.id.btPlay);

        mediaPlayer = MediaPlayer.create(this,R.raw.ding_dong);

    runnable = new Runnable() {
        @Override
        public void run() {
            seekBar.setProgress(mediaPlayer.getCurrentPosition());

            handler.postDelayed(this,500);
        }
    };

    int duration = mediaPlayer.getDuration();

  String sDuration = convertFormat(duration);

  playerDuration.setText(sDuration);

  btPlay.setOnClickListener(v -> {

      mediaPlayer.start();

      btPlay.setVisibility(View.GONE);

      btPause.setVisibility(View.VISIBLE);

      seekBar.setMax(mediaPlayer.getDuration());

      handler.postDelayed(runnable, 0)

  });

  btPause.setOnClickListener(v -> {

      mediaPlayer.stop();

      btPause.setVisibility(View.GONE);

      btPlay.setVisibility(View.VISIBLE);


      handler.removeCallbacks(runnable);

  });


  seekBar.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
      @Override
      public void onProgressChanged(CircularSeekBar circularSeekBar, float v, boolean b) {

          if (b) {

              mediaPlayer.seekTo((int) v);

          }
          playerPosition.setText(convertFormat(mediaPlayer.getCurrentPosition()));
      }

      @Override
      public void onStopTrackingTouch(CircularSeekBar circularSeekBar) {

      }

      @Override
      public void onStartTrackingTouch(CircularSeekBar circularSeekBar) {

      }
  });

  mediaPlayer.setOnCompletionListener(mp -> {
      btPause.setVisibility((View.GONE));

      btPlay.setVisibility(View.VISIBLE);

      mediaPlayer.seekTo(0);
  });

    }
}
@SuppressLint("DefaultLocale")
    private String convertFormat(int duration) {
        return String.format("%02d:%02d"
                ,TimeUnit.MILLISECONDS.toMinutes(duration)
                ,TimeUnit.MILLISECONDS.toSeconds(duration) -
                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)));
}
@Override
public void onPause()
{
    if(mediaPlayer != null && mediaPlayer.isPlaying())
    {
        mediaPlayer.stop();
    }
    super.onPause();
}

} 

The code I am using now:

 btPause = findViewById(R.id.btPauseMusic);
    btPlay = findViewById(R.id.btPlayMusic);

    btPlay.setOnClickListener(v -> {

        startService(new Intent(this, BackgroundMusicService.class));

        btPlay.setVisibility(View.GONE);

        btPause.setVisibility(View.VISIBLE);
    });

    btPause.setOnClickListener(v -> {

        stopService(new Intent(this, BackgroundMusicService.class));

        btPause.setVisibility(View.GONE);

        btPlay.setVisibility(View.VISIBLE);
    });

}

And the service class:

public class BackgroundMusicService extends Service {

private MediaPlayer mediaPlayer;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    mediaPlayer = MediaPlayer.create(this, R.raw.ding_dong);
    mediaPlayer.start();
    return START_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();

    mediaPlayer.stop();
}
}
2 Answers

You are using different MediaPlayer in the Activity from the one in the backgroundService you don't need to initialize another mediaPlayer in the activity you have to control the one in the backgroundService with Broadcast receivers like this for example to pause a the mediaPlayer in the backgroundService you do something like this

 private BroadcastReceiver pausePlayingAudio = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            pause();
            updateMetaData();
            buildNotification(PlaybackStatus.PAUSED);
            playbackStatus = PlaybackStatus.PAUSED ;

        }
    };
    private void register_pausePlayingAudio(){
        IntentFilter intentFilter = new IntentFilter(SongAdapter.ACTION_PAUSE) ;
        registerReceiver(pausePlayingAudio , intentFilter) ;
    }

and you call register_pausePlayingAudio() in onCreate() of the backGroundService

now say when a user clicks on a button in the activity and you want to pause you use something like this

sendBroadcast(new Intent(SongAdapter.ACTION_PAUSE));

I have and old project not finished doesn't have a seekBar but the seekBar implementation will be similar just instead of pause() you call seekTo() so you can check it

the repo

This article Creating Media player service shows step by step on how you can implement a service to create a Mediaplayer application to run in the background.

Related