본문

[2017.11.01] 66. Android 음악 플레이어 프로젝트 [알림바 추가]

도입

이번 포스팅에서는 지난 포스팅에 이어 음악 플레이어에 알림바를 추가하는 실습을 할 예정이다.

알림바를 컨트롤 하는 것은 참 어렵다.......


Android 음악 플레이어 프로젝트 [알림바 추가]의 데이터의 흐름

이번 포스팅에서는 Service로 전달 받은 선택된 음악의 정보(Title, Artist, Album, Picture)를 Notification에게 전달해 알림바를 구현할 것이다.


문제점 및 해결

1) 알림바 버튼 터치에 따른 버튼 아이콘 변경

알림바는 버튼이 터치되면 Pending Intent를 통해 자기 자신이 다시 호출된다. 버튼 아이콘의 모양은 현재 음악 플레이어의 상태에 따라 설정된다. 그래서 Next 버튼이나 Prev 버튼이 클릭되면 Pause, Play 버튼 모양이 Next, Prev 버튼 모양으로 변경된다. 

원인은 

1) Notification의 버튼이 클릭되었을 때 Pending Intent를 통해 재귀 함수처럼 Service 자신을 호출

2) 현재 상태를 기반으로 버튼의 상태가 결정된다.

1
2
3
4
// 알림바 버튼 생성
builder.addAction(makeButtonInNotification(Const.ACTION_MUSIC_PREV));
builder.addAction(makeButtonInNotification(currentStatus));
builder.addAction(makeButtonInNotification(Const.ACTION_MUSIC_NEXT));
cs

때문이다. 

그래서 코드를 다음과 같이 변경했다.

변경 전

변경 후

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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();
 
        break;
    case Const.ACTION_MUSIC_PREV:
        prev();
 
        break;
    }
}
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
    }
}
cs

코드

PlayerService.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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()*10000false);
 
        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();
    }
}
cs

스크린 샷

스크린 샷처럼 알림바의 버튼 동작하지만 알림바 버튼 동작에 따른 PlayMainViewActivity의 버튼은 동작하지 않는다. 이러한 문제점 다음 포스팅에서 처리할 예정이다.

 

 

#안드로이드 음악 플레이어 #안드로이드 mp3 #안드로이드 프로젝트  #앱개발 #모바일앱개발 #어플개발

공유

댓글