上一章写到如何发出一个通知。但是,通知既然作为一个View,它应该能与我们的业务逻辑有一系列交互。比如,我们可以通过Notification的remoteview中的Button控制一下业务逻辑(如播放/暂停音乐),或者用进度条显示后台操作的进度。在此我写了一个简单的音乐播放器。我们能够在Notification的remoteview中的Button,控制音乐的播放,通过其中的进度条,得知播放音乐的进度。
Notification的初始化为
private void initNotification(){ Intent intentService = new Intent(this , MusicPlayService.class); // 开启音乐Service this.startService(intentService); String notifyTitle = "这是消息的标题"; String notifyContent = "这是消息的内容"; // 建立点击Intent Intent intent = new Intent(this , NotifyDesActivity.class); intent.putExtra("title" , notifyTitle); intent.putExtra("content", notifyContent); PendingIntent pendingIntent = PendingIntent.getActivity(this, NOTIFY_DES, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 将notification的布局引入 remoteViews = new RemoteViews(getPackageName() , R.layout.notify_layout); // 发送播放音乐的广播 Intent intentStart = new Intent(); intentStart.setAction(MusicPlayService.MUSIC_COMMAN_INTENTFILTER); intentStart.putExtra(MusicPlayService.MUSIC_COMMAND_KEY, MusicPlayService.START_MUSIC_COMMAND); PendingIntent pendingIntentStart = PendingIntent.getBroadcast(this, MusicPlayService.START_MUSIC_COMMAND, intentStart, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.start_btn , pendingIntentStart); // 发送停止音乐的广播 Intent intentStop = new Intent(); intentStop.setAction(MusicPlayService.MUSIC_COMMAN_INTENTFILTER); intentStop.putExtra(MusicPlayService.MUSIC_COMMAND_KEY, MusicPlayService.STOP_MUSIC_COMMAND); PendingIntent pendingIntentStop = PendingIntent.getBroadcast(this , MusicPlayService.STOP_MUSIC_COMMAND , intentStop , PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.cancel_btn , pendingIntentStop); // 创建notificationpu 实例 notifyBuilder = new NotificationCompat.Builder(this) // 通知时的图标 .setSmallIcon(R.drawable.add_group_btn_img) // 下拉窗中的通知布局 .setContent(remoteViews) // 通知时的提示 .setTicker("收到一条消息") // 通知被点击时的事件 .setContentIntent(pendingIntent) // 通知被点击后是否自动关闭 .setAutoCancel(true); }
这样当我们单击R.id.start_btn和R.id.cancel_btn时,即会分别会发现intentStart和intentStop两个广播,通知后台处理音乐播放的逻辑。
当需要发送通知时
private synchronized void sendNotification(){ Intent intentService = new Intent(this , MusicPlayService.class); // 开启音乐Service this.startService(intentService); // 获取默认通知铃声,此处可以自己设置 Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); // 为通知设置铃声 notifyBuilder.setSound(soundUri); // 为通知设置振动 停1000ms 震200ms 停1000ms 震200ms notifyBuilder.setVibrate(new long[]{1000, 200, 1000, 200}); // 设置通知ID,并发出通知 Notification notification = notifyBuilder.build(); notification.flags = Notification.FLAG_NO_CLEAR; notificationManager.notify(UPLOAD_IMAGE, notification); notifyBuilder.setSound(null); notifyBuilder.setVibrate(null); }
MusicPlayService的任务有两个:
1) 根据接收到的广播控制音乐的播放停止逻辑
2) 根据当前的音乐播放状态,将进度条、是否正在播放等信息以广播的形式发出,改变Notification的外观。
public class MusicPlayService extends Service { static final String MUSIC_COMMAND_KEY = "music_command"; static final String MUSIC_PROCCESS = "music_proccess"; static final String MUSIC_COMMAN_INTENTFILTER = "music_command_intent_filter"; static final int START_MUSIC_COMMAND = 1001; static final int STOP_MUSIC_COMMAND = 1002; static final int PAUSE_MUSIC_COMMAND = 1003; final int MUSIC_STATE_STOP = 0; final int MUSIC_STATE_START = 1; final int MUSIC_STATE_PAUSE = 2; int musicState = MUSIC_STATE_STOP; MusicServiceReceiver musciReceiver; MediaPlayer mMusicPlayer; TimerTask timerTask; Timer timer; boolean timeIsAlive = false; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); // 初始化音乐播放器 mMusicPlayer = new MediaPlayer(); mMusicPlayer.setLooping(false); // 音乐广播接收器 musciReceiver = new MusicServiceReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(MUSIC_COMMAN_INTENTFILTER); registerReceiver(musciReceiver, intentFilter); readyAssetsMusic(mMusicPlayer); // 当时发送音乐播放进度,改变进度条 timerTask = new TimerTask() { @Override public void run() { if (mMusicPlayer != null && mMusicPlayer.isPlaying()&&timeIsAlive) { float duration = mMusicPlayer.getDuration(); Log.d("tag", "当前播放到======" + mMusicPlayer.getCurrentPosition() / duration * 100 + "%"); Intent intent = new Intent(); intent.setAction(MainActivity.MUSIC_ACTIVITY_ACTION); intent.putExtra(MUSIC_PROCCESS, (int) (mMusicPlayer.getCurrentPosition() / duration * 100)); sendBroadcast(intent); } } }; timer = new Timer(); timer.schedule(timerTask, 2000, 1000); } // 广播接收器 public class MusicServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("tag", "收到了广播消息"); int command = intent.getIntExtra(MUSIC_COMMAND_KEY, -1); switch (command) { //开始音乐 case START_MUSIC_COMMAND: if (musicState == MUSIC_STATE_START) { //发送状态信息 Intent pauseIntent = new Intent(); pauseIntent.setAction(MainActivity.MUSIC_ACTIVITY_ACTION); pauseIntent.putExtra(MUSIC_COMMAND_KEY, PAUSE_MUSIC_COMMAND); sendBroadcast(pauseIntent); // 控制音乐播放 mMusicPlayer.pause(); // 处理音乐逻辑 timeIsAlive = false; musicState = MUSIC_STATE_PAUSE; } else if (musicState == MUSIC_STATE_PAUSE || musicState == MUSIC_STATE_STOP) { //发送状态信息 Intent startIntent = new Intent(); startIntent.setAction(MainActivity.MUSIC_ACTIVITY_ACTION); startIntent.putExtra(MUSIC_COMMAND_KEY, START_MUSIC_COMMAND); sendBroadcast(startIntent); // 控制音乐播放 mMusicPlayer.start(); // 处理音乐逻辑 timeIsAlive = true; musicState = MUSIC_STATE_START; } break; // 停止音乐 case STOP_MUSIC_COMMAND: if (musicState == MUSIC_STATE_START || musicState == MUSIC_STATE_PAUSE) { //发送状态信息 Intent stopIntent = new Intent(); stopIntent.setAction(MainActivity.MUSIC_ACTIVITY_ACTION); stopIntent.putExtra(MUSIC_COMMAND_KEY, STOP_MUSIC_COMMAND); stopIntent.putExtra(MUSIC_PROCCESS , 0); sendBroadcast(stopIntent); // 控制音乐播放 mMusicPlayer.pause(); mMusicPlayer.seekTo(0); // 处理音乐逻辑 timeIsAlive = false; musicState = MUSIC_STATE_STOP; } break; } } } /** * 读取assets中的文件 * @param mediaPlayer 播放器实例 */ private void readyAssetsMusic(MediaPlayer mediaPlayer) { if (mediaPlayer == null) { return; } try { AssetFileDescriptor afd = getAssets().openFd("music1.mp3"); mediaPlayer.reset(); mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } } }
MusicPlayService将音乐播放状态传给MainActivity。根据传来的信息,MainActivity将remoteview中的外观进行修改,并更新。
public class MusicActivityReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { int proccess = intent.getIntExtra(MusicPlayService.MUSIC_PROCCESS , -1); int command = intent.getIntExtra(MusicPlayService.MUSIC_COMMAND_KEY , 0); if (proccess >= 0){ remoteViews.setProgressBar(R.id.notify_progress , 100 , proccess ,false); } switch (command){ case MusicPlayService.START_MUSIC_COMMAND: remoteViews.setTextViewText(R.id.start_btn, "暂停"); break; case MusicPlayService.STOP_MUSIC_COMMAND: remoteViews.setTextViewText(R.id.start_btn, "播放"); break; case MusicPlayService.PAUSE_MUSIC_COMMAND: remoteViews.setTextViewText(R.id.start_btn, "播放"); break; } updateNotification(); } } /** * 注册广播,接收来自MusicService的广播命令 */ private void initReceiver(){ musicReceiver = new MusicActivityReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(MUSIC_ACTIVITY_ACTION); registerReceiver(musicReceiver , intentFilter); } // 更新通知信息 private synchronized void updateNotification() { notificationManager.notify(UPLOAD_IMAGE, notifyBuilder.build()); }
Done!