제가 작성한 tistory글의 마이그레이션입니다.
이번 포스팅에서는 지난 포스팅에 이어 음악 플레이어에 알림바를 추가하는 실습을 할 예정이다.
알림바를 컨트롤 하는 것은 참 어렵다.......
이번 포스팅에서는 Service로 전달 받은 선택된 음악의 정보(Title, Artist, Album, Picture)를 Notification에게 전달해 알림바를 구현할 것이다.
원인은
1. Notification의 버튼이 클릭되었을 때 Pending Intent를 통해 재귀 함수처럼 Service 자신을 호출
2. 현재 상태를 기반으로 버튼의 상태가 결정된다.
// 알림바 버튼 생성
builder.addAction(makeButtonInNotification(Const.ACTION_MUSIC_PREV));
builder.addAction(makeButtonInNotification(currentStatus));
builder.addAction(makeButtonInNotification(Const.ACTION_MUSIC_NEXT));
때문이다.
그래서 코드를 다음과 같이 변경했다.
public class PlayerService extends Service implements SeekbarThread.IObserver {
switch (currentStatus) {
case Const.ACTION_MUSIC_SET:
currentMusic = intent.getParcelableExtra("currentMusic");
setMusic();
play();
currentStatus = Const.ACTION_MUSIC_PLAY;
break;
case Const.ACTION_MUSIC_PLAY:
play();
break;
case Const.ACTION_MUSIC_PAUSE:
pause();
break;
case Const.ACTION_MUSIC_NEXT:
next();
// 버튼을 위해
currentStatus = Const.ACTION_MUSIC_PLAY;
break;
case Const.ACTION_MUSIC_PREV:
prev();
// 버튼을 위해
currentStatus = Const.ACTION_MUSIC_PLAY;
break;
}
}
public class PlayerService extends Service {
// ...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
currentStatus = intent.getAction();
switch (currentStatus) {
case Const.ACTION_MUSIC_SET:
currentMusic = intent.getParcelableExtra("currentMusic");
setMusic();
play();
currentStatus = Const.ACTION_MUSIC_PLAY;
break;
case Const.ACTION_MUSIC_PLAY:
play();
break;
case Const.ACTION_MUSIC_PAUSE:
pause();
break;
case Const.ACTION_MUSIC_NEXT:
next();
// Notification 버튼을 위해
currentStatus = Const.ACTION_MUSIC_PLAY;
break;
case Const.ACTION_MUSIC_PREV:
prev();
// Notification 버튼을 위해
currentStatus = Const.ACTION_MUSIC_PLAY;
break;
}
startForeground(11, makeNotification());
return super.onStartCommand(intent, flags, startId);
}
// 알림바 생성 메소드
private Notification makeNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Notification LargeIcon 설정
Bitmap largeIcon = null;
try {
largeIcon
= MediaStore.Images.Media.getBitmap
(getContentResolver(), currentMusic.getAlbumUri());
} catch (IOException e) {
e.printStackTrace();
}
builder .setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(currentMusic.getTitle())
.setContentText(currentMusic.getArtist())
.setLargeIcon(largeIcon);
builder.addAction(makeButtonInNotification(Const.ACTION_MUSIC_PREV));
builder.addAction(makeButtonInNotification(currentStatus));
builder.addAction(makeButtonInNotification(Const.ACTION_MUSIC_NEXT));
// 알람바 프로그래스바 추가
Log.i("heepie", CLASSNAME + currentMusic.getSecDuration());
builder.setProgress(currentMusic.getSecDuration()*1000, 0, false);
return builder.build();
}
// 알림바 버튼 생성 메소드(Prev, Play, Pause, Next)
private NotificationCompat.Action makeButtonInNotification(String action) {
int iconId = 0;
// 현재 액션 후 다음 클릭 시 다음 액션 설정
// 임의의 버튼 아이콘 등록
switch (action) {
case Const.ACTION_MUSIC_PLAY:
iconId = android.R.drawable.ic_media_pause;
action = Const.ACTION_MUSIC_PAUSE;
break;
case Const.ACTION_MUSIC_PAUSE:
iconId = android.R.drawable.ic_media_play;
action = Const.ACTION_MUSIC_PLAY;
break;
case Const.ACTION_MUSIC_NEXT:
iconId = android.R.drawable.ic_media_next;
break;
case Const.ACTION_MUSIC_PREV:
iconId = android.R.drawable.ic_media_previous;
break;
}
// PendingIntent로 등록될 Intent 생성
Intent intent = new Intent(getBaseContext(), PlayerService.class);
// Intent로 전달될 액션 설정
intent.setAction(action);
// PendingIntent 생성
PendingIntent pendingIntent
= PendingIntent.getService(getBaseContext(), 1, intent, 0);
// 버튼 타이틀 등록
String btnTitle = action;
// 해당 버튼 액션 설정
NotificationCompat.Action notifAction
= new NotificationCompat.Action.Builder
(iconId, btnTitle, pendingIntent).build();
return notifAction;
}
private void setMusic() {
// Uri로 Player 설정
playerController.setMusic(currentMusic.getMusicUri());
}
private void play() {
playerController.play();
currentStatus = Const.ACTION_MUSIC_PLAY;
}
private void pause() {
playerController.pause();
currentStatus = Const.ACTION_MUSIC_PAUSE;
}
private void next() {
playerController.next();
}
private void prev() {
playerController.prev();
}
}
스크린 샷처럼 알림바의 버튼 동작하지만 알림바 버튼 동작에 따른 PlayMainViewActivity의 버튼은 동작하지 않는다. 이러한 문제점은 다음 포스팅에서 처리할 예정이다.