概述
通知(Notification)就是程序在不影响用户操作的情况下,通过手机顶部弹出消息告诉用户的一种信息通知方式,并且可以通过下拉通知操作抽屉通知,实现Notification与活动、通知和服务通信。例如:通知与活动相互通信,活动通过NotificationManager发送通知(创建通知),而抽屉通知里面的操作则通过发送广播事件传递信息,此时活动只要已经注册过该广播事件的接收器,那么就能接收到通知的信息,从而实现通知和活动交互。
例子(通知和活动同步音乐播放和暂停)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/bg"
android:scaleType="fitXY"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play_over"
android:layout_gravity="center"
android:clickable="true"
android:id="@+id/imageView"
android:background="@drawable/img_bg"/>
</FrameLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#e0e0e0"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView1"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="@drawable/sc"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_control"
android:clickable="true"
android:padding="4dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/play_over"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/image_control"
android:padding="4dp"
android:text="Sweet Child O' Mine"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/tv_nowTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/image_control"
android:text="00:00"
android:layout_alignParentBottom="true"/>
<TextView
android:id="@+id/tv_totallTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:text="00:00"/>
</RelativeLayout>
</LinearLayout>
package com.liujun.activity;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import com.liujun.liujunmusicnotification.R;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.RemoteViews;
public class MainActivity extends Activity {
private MediaPlayer mediaPlayer;//媒体播放器
private NotificationManager notificationManager;//通知管理器
private ImageView imageView;//播放音乐图片按钮
private boolean isPlaying=false;//是否正在播放音乐
//意图
public static final String PLAYMUSIC_INTENT="PLAYMUSIC_INTENT";
public static final String PAUSEMUSIC_INTENT="PAUSEMUSIC_INTENT";
//通知标识ID
public static final int NOTIFICATION_ID=1;
//时间计时器
private Timer timer;
private MyBroadCastRecever recever;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mian_activity);
//实例化媒体播放器
mediaPlayer=MediaPlayer.create(this, R.raw.sc);
//实例化通知管理器
notificationManager=(NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
timer=new Timer();
imageView=(ImageView) this.findViewById(R.id.imageView);
imageView.setOnClickListener(onClickListener);
//注册接收通知栏发送的广播事件
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction(PAUSEMUSIC_INTENT);
intentFilter.addAction(PLAYMUSIC_INTENT);
recever=new MyBroadCastRecever();
this.registerReceiver(recever, intentFilter);
}
OnClickListener onClickListener=new OnClickListener() {
@Override
public void onClick(View v) {
if (!isPlaying) {//没有播放音乐
//开始播放音乐
playMusic();
//更改图片背景
imageView.setImageResource(R.drawable.pause_over);
//更改标志
isPlaying=true;
}else {//正在播放音乐
//暂停播放音乐
pauseMusic();
//更改图片背景
imageView.setImageResource(R.drawable.play_over);
//更改标志
isPlaying=false;
}
//发送通知栏
activitySendNotification();
}
};
/**
* 播放音乐
*/
protected void playMusic() {
if (mediaPlayer==null) {
mediaPlayer=MediaPlayer.create(MainActivity.this, R.raw.sc);
}
if (timer==null) {
timer=new Timer();
}
//开启计时器任务,每个一秒 更新抽屉通知音乐播放进度
timer.schedule(new MyTimerTask(), 0, 1000);
//播放音乐
mediaPlayer.start();
}
//时间任务,更新抽屉通知,播放进度(注意:每次调用必须重新new)
private class MyTimerTask extends TimerTask{
@Override
public void run() {
//活动端发送通知
activitySendNotification();
}
}
/**
* 发送通知
*/
protected void activitySendNotification() {
//通知构建器
NotificationCompat.Builder builder=new NotificationCompat.Builder(this);
//设置小图标
builder.setSmallIcon(R.drawable.favorite);
//加载自定义远程布局
RemoteViews remoteView=(RemoteViews) new RemoteViews(this.getPackageName(), R.layout.my_notification);
//设置不可以拉动取消抽屉通知
builder.setOngoing(true);
//设置标题
remoteView.setTextViewText(R.id.tv_title, "Sweet Child O' Mine");
//当前播放时间(注意:当进入界面播放音乐时退出界面,不是暂停时退出界面,那么就有可能在程序执行
//onDestroy()方法时将mediaPlayer释放并置空了,而此段代码是在子线程中的,与主线程不同步退出,
//那么就导致mediaPlayer为空,从而报错)
if (mediaPlayer==null) {
return;
}
Date currentDate=new Date(mediaPlayer.getCurrentPosition());
//总时长
Date totalDate=new Date(mediaPlayer.getDuration());
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("mm:ss");
//设置当前播放时间进度
remoteView.setTextViewText(R.id.tv_nowTime, simpleDateFormat.format(currentDate));
//设置歌曲总时长
remoteView.setTextViewText(R.id.tv_totallTime, simpleDateFormat.format(totalDate));
Log.i("liujun", "是否正在播放音乐:--"+isPlaying);
if (isPlaying) {//正在播放音乐
//显示可以暂停图片
remoteView.setImageViewResource(R.id.image_control, R.drawable.pause_over);
}else {
//显示可以播放图片
remoteView.setImageViewResource(R.id.image_control, R.drawable.play_over);
}
//通知栏,交互互动
notificationToActivity(remoteView,isPlaying);
//加载视图布局
builder.setContent(remoteView);
//创建通知
Notification notification=builder.build();
//发送通知
notificationManager.notify(NOTIFICATION_ID, notification);
}
/**
* 通知栏交互活动
* @param isPlaying
*/
private void notificationToActivity(RemoteViews remoteView,boolean isPlaying) {
Intent intent=new Intent();
if (isPlaying) {//正在播放音乐
//试图暂停播放音乐
intent.setAction(PAUSEMUSIC_INTENT);
//更改图片
remoteView.setImageViewResource(R.id.image_control, R.drawable.pause_over);
/* //更新标志
isPlaying=false;*/
}else {//没有播放音乐
//试图播放音乐
intent.setAction(PLAYMUSIC_INTENT);
//更改图片
remoteView.setImageViewResource(R.id.image_control, R.drawable.play_over);
/*//更新标志
isPlaying=true;*/
}
//发送广播,更新Activity
PendingIntent pendingIntent=PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setOnClickPendingIntent(R.id.image_control, pendingIntent);
}
//广播接收器(接收通知发送的广播事件)
private class MyBroadCastRecever extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction()==PLAYMUSIC_INTENT) {//通知端播放音乐
//播放音乐
playMusic();
//是否播放正在播放音乐标志
isPlaying=true;
//更改图片标志
imageView.setImageResource(R.drawable.pause_over);
}else if(intent.getAction()==PAUSEMUSIC_INTENT){//通知端暂停音乐
//暂停音乐
pauseMusic();
//是否播放正在播放音乐标志
isPlaying=false;
//更改图片标志
imageView.setImageResource(R.drawable.play_over);
}
//上面更新活动的信息,这时又要发送通知
activitySendNotification();
}
}
/**
* 暂停播放音乐
*/
protected void pauseMusic() {
if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
//暂停发送通知
if (timer!=null) {
timer.cancel();
timer=null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
this.unregisterReceiver(recever);
//释放资源
if (mediaPlayer!=null) {
mediaPlayer.release();
mediaPlayer=null;
}
//是否通知栏
notificationManager.cancel(NOTIFICATION_ID);
}
}