Android实战 – 音心播放器 (通知实现音乐的播放/暂停/下一曲控制)

最后更新于:2022-04-01 10:52:45

## 1.背景     **通知 -> Service :**    上一篇的MusicService 中提高了通知是Service的前台显示,这篇将介绍通知(MusicNotification).通知在这里有四个作用:     (1)显示当前音乐的信息     (2)播放/暂停音乐     (3)下一曲播放音乐     (4)关闭通知栏(实际上也是停止音乐播放并关闭Service)    **Service -> 通知 :**     通知和Service是紧密相连的,当Service结束的时候,取消通知;当Service启动的时候,初始化通知/创建通知;当音乐状态发生改变的时候,更新通知;如下图所示 :                                                        ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764c1ff57.jpg) ## 2.通知实现       在这里单独的将通知单独的类中,方便使用;没有使用到通知的震动提醒/铃声提醒/闪光灯提醒,如果需要使用,可以看博客 :  [Android-Notification (通知实现)](http://blog.csdn.net/lablenet/article/details/47999961). ###    (1)通知布局实现 ~~~ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" > <ImageView android:id="@+id/iv_notification_logo" android:layout_width="60dp" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_margin="5dp" android:src="@drawable/logo" /> <TextView android:id="@+id/tv_nofitication_singname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_toRightOf="@+id/iv_notification_logo" android:maxLines="1" android:textSize="12sp" android:text="@string/item_notification_singname" android:textColor="@color/text_color_whrit" /> <TextView android:id="@+id/tv_nofitication_singer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="10dp" android:textSize="10sp" android:layout_toRightOf="@+id/iv_notification_logo" android:text="@string/item_notifiaction_singer" android:textColor="@color/bg_color" /> <ImageView android:id="@+id/iv_nofitication_kzhi_play" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginTop="20dp" android:layout_marginBottom="10dp" android:layout_toLeftOf="@+id/iv_nofitication_kzhi_next" android:src="@android:drawable/ic_media_play" /> <ImageView android:id="@+id/iv_nofitication_kzhi_next" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginTop="20dp" android:layout_marginBottom="10dp" android:layout_toLeftOf="@+id/iv_nofitication_kzhi_colse" android:src="@android:drawable/ic_media_next" /> <ImageView android:id="@+id/iv_nofitication_kzhi_colse" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentRight="true" android:layout_marginTop="20dp" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" android:layout_marginLeft="10dp" android:src="@android:drawable/ic_menu_close_clear_cancel" android:textColor="@color/text_color_main" /> </RelativeLayout> ~~~             效果 :                                                             ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764c30864.jpg) ###     (2)代码实现 说明: 1)通知的实现是单例模式实现(恶汉式)(  [设计模式之单例模式(Singleton pattern)](http://blog.csdn.net/lablenet/article/details/50014001) ); 2)通知中通过使用RemoteViews ,进行自定义布局实现; 3)通过PendingIntent来封装响应点击事件的Intent ;  4)第3条中的Intent,经过测试,只能每个响应事件,填充参数的Intent,只能对应一个点击事件 , 否则是得不到Intent中的参数的。但如果不需要区分的话,一个Intent就可以实现点击事件的响应; 5)通过PendingInetnt.getBroadcast() 方法来通知MusicService,进行响应事件的本质作用;  6)广播:如果MusicService想要接收到通知来的点击事件,那么需要在MusicServiceBroadcast中                         注册(IntentFiliter/addAction(xxx)),同时通知中的Inent需 要setAction(xxx), xxx 要一样; **实现的通知源码分享 :** ~~~ package cn.labelnet.framework; import com.android.volley.toolbox.ImageLoader.ImageListener; import android.R.anim; import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.os.Build; import android.widget.RemoteViews; import cn.labelnet.maskmusic.R; import cn.labelnet.model.MusicModel; import cn.labelnet.net.VolleyHttpRequest; public class MusicNotification extends Notification { /** * Music播放控制 的 Notification * 动态的显示后台的MusicService的前台展示 */ /** * 恶汉式实现单例模式加载 */ private static MusicNotification notifyInstance = null; // 通知id private final int NOTIFICATION_ID = 10001; // 通知 private Notification musicNotifi = null; // 管理通知 private NotificationManager manager = null; // 界面实现 private Builder builder = null; // 上下文 private Context context; // 布局 private RemoteViews remoteViews; private final int REQUEST_CODE = 30000; // 给Service 发送广播 private final String MUSIC_NOTIFICATION_ACTION_PLAY = "musicnotificaion.To.PLAY"; private final String MUSIC_NOTIFICATION_ACTION_NEXT = "musicnotificaion.To.NEXT"; private final String MUSIC_NOTIFICATION_ACTION_CLOSE = "musicnotificaion.To.CLOSE"; private final String MUSIC_NOTIFICAION_INTENT_KEY = "type"; private final int MUSIC_NOTIFICATION_VALUE_PLAY = 30001; private final int MUSIC_NOTIFICATION_VALUE_NEXT = 30002; private final int MUSIC_NOTIFICATION_VALUE_CLOSE =30003; private Intent play=null,next=null,close = null; private PendingIntent musicPendIntent = null; // 给进度条页面广播 // 待实现 // 网络 : 加载图片实现 private ImageListener imageListener = null; public void setManager(NotificationManager manager) { this.manager = manager; } public void setContext(Context context) { this.context = context; } private MusicNotification() { // 初始化操作 remoteViews = new RemoteViews("cn.labelnet.maskmusic", R.layout.list_item_notification); builder = new Builder(context); // 初始化控制的Intent play = new Intent(); play.setAction(MUSIC_NOTIFICATION_ACTION_PLAY); next = new Intent(); next.setAction(MUSIC_NOTIFICATION_ACTION_NEXT); close = new Intent(); close.setAction(MUSIC_NOTIFICATION_ACTION_CLOSE); } /** * 恶汉式实现 通知 * * @return */ public static MusicNotification getMusicNotification() { if (notifyInstance == null) { notifyInstance = new MusicNotification(); } return notifyInstance; } /** * 创建通知 * 初始化通知 */ @SuppressLint("NewApi") public void onCreateMusicNotifi() { // 设置点击事件 // 1.注册控制点击事件 play.putExtra("type", MUSIC_NOTIFICATION_VALUE_PLAY); PendingIntent pplay = PendingIntent.getBroadcast(context, REQUEST_CODE, play, NOTIFICATION_ID); remoteViews.setOnClickPendingIntent(R.id.iv_nofitication_kzhi_play, pplay); // 2.注册下一首点击事件 next.putExtra("type", MUSIC_NOTIFICATION_VALUE_NEXT); PendingIntent pnext = PendingIntent.getBroadcast(context, REQUEST_CODE, next, NOTIFICATION_ID); remoteViews.setOnClickPendingIntent(R.id.iv_nofitication_kzhi_next, pnext); // 3.注册关闭点击事件 close.putExtra("type", MUSIC_NOTIFICATION_VALUE_CLOSE); PendingIntent pclose = PendingIntent.getBroadcast(context, REQUEST_CODE, close, NOTIFICATION_ID); remoteViews.setOnClickPendingIntent(R.id.iv_nofitication_kzhi_colse, pclose); builder.setContent(remoteViews).setWhen(System.currentTimeMillis()) // 通知产生的时间,会在通知信息里显示 // .setPriority(Notification.PRIORITY_DEFAULT) // 设置该通知优先级 .setOngoing(true).setTicker("播放新的一首歌") .setSmallIcon(R.drawable.logo); // 兼容性实现 musicNotifi = builder.getNotification(); // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { // musicNotifi = builder.getNotification(); // } else { // musicNotifi = builder.build(); // } musicNotifi.flags = Notification.FLAG_ONGOING_EVENT; manager.notify(NOTIFICATION_ID, musicNotifi); } /** * 更新通知 */ public void onUpdataMusicNotifi(MusicModel mm, boolean isplay) { // 设置添加内容 remoteViews.setTextViewText(R.id.tv_nofitication_singname, (mm.getSongname()!=null?mm.getSongname():"什么东东") + ""); remoteViews.setTextViewText(R.id.tv_nofitication_singer, (mm.getSingername()!=null?mm.getSingername():"未知") + ""); //判断是否播放 if (isplay) { remoteViews.setImageViewResource(R.id.iv_nofitication_kzhi_play, android.R.drawable.ic_media_pause); } else { remoteViews.setImageViewResource(R.id.iv_nofitication_kzhi_play, android.R.drawable.ic_media_play); } onCreateMusicNotifi(); } /** * 取消通知栏 */ public void onCancelMusicNotifi(){ manager.cancel(NOTIFICATION_ID); } } ~~~ ### (3)广播的基本使用图解    ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764c432dd.jpg) ## 3.总结 通知的更新控制是在音乐状态发生改变的时候,就会更新通知的内容;相反通知也可以控制音乐当前的状态;后面还有音乐播放界面的控制,省去了很多事,简单的在Service 中调用就可以实现。    MusicService 与 MusicNotification 的基本控制图 ,如下图所示 : ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764c5c679.jpg) 音乐的播放/暂停/上一曲/下一曲/停止 基本控制 是在MusicService中实现的,所以请看  [Android实战 - 音心播放器 (Music Service 实现)](http://blog.csdn.net/lablenet/article/details/50322487);
';