本文根据原生Android 4.1.1 Music 源码做修改。
1 原生Music 暂停的时候,会删除通知栏上的通知。
2 原生Music 通知栏不能控制音乐,比如下一首,上一首,暂停/播放。
一 解决思路:
1 接到暂停广播时,只暂停,不去除通知。
/packages/apps/Music/src/com/android/music/MediaPlaybackService.java中
调用的 stopForeground(true)方法控制去除通知
2 自定义音乐通知,添加按钮事件。
/packages/apps/Music/src/com/android/music/MediaPlaybackService.java中
updateNotification()方法中自定义Notification,关键对RemoteViews 的理解
二 修改后效果图:
三 详细代码
1 接到暂停广播时,只暂停,不去除通知
源代码 采取的策略是 只要暂停就去除通知,这就会造成一个问题就是,当播放视频的时候音乐播放器接受到暂停的广播,于是消除了通知栏。
1.1 添加暂停 不消除通知的方法 pause(boolean isStopForeground)
- private void pause(boolean isStopForeground) {
- synchronized(this) {
- mMediaplayerHandler.removeMessages(FADEUP);
- if (isPlaying()) {
- mPlayer.pause();
- gotoIdleState(isStopForeground);
- mIsSupposedToBePlaying = false;
- notifyChange(PLAYSTATE_CHANGED);
- saveBookmarkIfNeeded();
- }
- }
- }
-
- private void gotoIdleState(boolean isStopForeground) {
- mDelayedStopHandler.removeCallbacksAndMessages(null);
- Message msg = mDelayedStopHandler.obtainMessage();
- mDelayedStopHandler.sendMessageDelayed(msg, IDLE_DELAY);
-
- stopForeground(isStopForeground);
- }
1.2 接收暂停广播的时候将pause()方法换为:pause(false)
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- String cmd = intent.getStringExtra("command");
- MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);
- if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
- gotoNext(true);
- } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
- prev();
- } else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {
- if (isPlaying()) {
-
- pause(false);
- updateNotification();
-
- mPausedByTransientLossOfFocus = false;
- } else {
- play();
- }
- } else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {
-
- pause(false);
- updateNotification();
-
- mPausedByTransientLossOfFocus = false;
- } else if (CMDPLAY.equals(cmd)) {
- ...
2 Music 音乐通知控制
2.1 通知的布局文件 /packages/apps/Music/res/layout/statusbar.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_vertical">
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:padding="4dip" >
- </ImageView>
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <TextView
- android:id="@+id/trackname"
- style="@android:style/TextAppearance.StatusBar.EventContent.Title"
- android:layout_width="80dip"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:ellipsize="marquee"
- android:focusable="true"
- android:singleLine="true" />
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <ImageButton
- android:id="@+id/statusbar_prev"
- style="@android:style/MediaButton.Previous"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true" />
-
- <ImageButton
- android:id="@+id/statusbar_pause"
- style="@android:style/MediaButton.Pause"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true" />
-
- <ImageButton
- android:id="@+id/statusbar_next"
- style="@android:style/MediaButton.Next"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:gravity="right" />
- </RelativeLayout>
- </LinearLayout>
-
- <TextView
- android:id="@+id/artistalbum"
- style="@android:style/TextAppearance.StatusBar.EventContent"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:ellipsize="end"
- android:maxLines="2"
- android:scrollHorizontally="true" />
- </LinearLayout>
-
- </LinearLayout>
2.2 通知栏控制:
/packages/apps/Music/src/com/android/music/MediaPlaybackService.java中
updateNotification()为发送的通知代码,在这里面修改
- private void updateNotification() {
-
- RemoteViews views = new RemoteViews(getPackageName(), R.layout.statusbar);
- views.setImageViewResource(R.id.icon, R.drawable.stat_notify_musicplayer);
- if (getAudioId() < 0) {
-
- views.setTextViewText(R.id.trackname, getPath());
- views.setTextViewText(R.id.artistalbum, null);
- } else {
- String artist = getArtistName();
- views.setTextViewText(R.id.trackname, getTrackName());
- if (artist == null || artist.equals(MediaStore.UNKNOWN_STRING)) {
- artist = getString(R.string.unknown_artist_name);
- }
- String album = getAlbumName();
- if (album == null || album.equals(MediaStore.UNKNOWN_STRING)) {
- album = getString(R.string.unknown_album_name);
- }
-
- views.setTextViewText(R.id.artistalbum,
- getString(R.string.notification_artist_album, artist, album)
- );
- }
- Notification status = new Notification();
-
-
- int status_icon = R.drawable.ic_appwidget_music_play;
-
- if(isPlaying()){
- views.setImageViewResource(R.id.statusbar_pause, R.drawable.ic_appwidget_music_pause);
- }else{
- views.setImageViewResource(R.id.statusbar_pause, R.drawable.ic_appwidget_music_play);
- status_icon = R.drawable.ic_appwidget_music_pause;
- }
-
- views.setOnClickPendingIntent(R.id.statusbar_prev, pre_PendingIntent());
-
- views.setOnClickPendingIntent(R.id.statusbar_pause, pause_PendingIntent());
-
- views.setOnClickPendingIntent(R.id.statusbar_next, next_PendingIntent());
-
-
- status.contentView = views;
- status.flags |= Notification.FLAG_ONGOING_EVENT;
- status.icon = status_icon;
- status.contentIntent = PendingIntent.getActivity(this, 0,
- new Intent("com.android.music.PLAYBACK_VIEWER")
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
- startForeground(PLAYBACKSERVICE_STATUS, status);
- }
添加的点击事件函数:
-
-
- private PendingIntent pre_PendingIntent(){
- Intent intent = new Intent(PREVIOUS_ACTION);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
- return pendingIntent;
- }
-
- private PendingIntent pause_PendingIntent(){
- Intent intent = new Intent(TOGGLEPAUSE_ACTION);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
- return pendingIntent;
- }
-
- private PendingIntent next_PendingIntent(){
- Intent intent = new Intent(NEXT_ACTION);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
- return pendingIntent;
- }
-
-
为了实现暂停/开始按钮通知栏图标显示与音乐播放 的一致 改了以下两个地方:
其一 play() 方法中 将 updateNotification() 放在了
if (!mIsSupposedToBePlaying) {
mIsSupposedToBePlaying = true;
notifyChange(PLAYSTATE_CHANGED);
}
之后
- public void play() {
- ...
- if (!mIsSupposedToBePlaying) {
- mIsSupposedToBePlaying = true;
- notifyChange(PLAYSTATE_CHANGED);
- }
- updateNotification();
- ...
- }
其二:当接受到 暂停/开始 事件的 广播后,如果 暂停音乐,则调用updateNotification()更新方法
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- String cmd = intent.getStringExtra("command");
- MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);
- Log.e(LOGTAG, " mIntentReceiver action = "+action+" cmd ="+cmd+"===");
- if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
- gotoNext(true);
- } else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
- prev();
- } else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {
- if (isPlaying()) {
-
-
- pause(false);
- updateNotification();
-
- mPausedByTransientLossOfFocus = false;
- } else {
- play();
- }
- ...