本文用的是
import android.support.v4.app.NotificationCompat;下面的Notification.
Notification,是一种具有全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它将先以图标的形式显示在通知栏中。用户可以下拉通知栏查看通知的详细信息。通知栏和抽屉式通知栏均是由系统控制,用户可以随时查看。
通知的目的是告知用户 App 事件。在平时的使用中,通知主要有以下几个作用:
- 显示接收到短消息、及时消息等信息(如QQ、微信、新浪、短信)
- 显示客户端的推送消息,如广告、优惠、版本更新、推荐新闻等,常用的第三方 SDK 有: JPush 、 个推 、 信鸽 、 网易云信(偏重 IM ) 、 阿里云推送
- 显示正在进行的事物,例如:后台运行的程序,如音乐播放进度、下载进度等
其中,前两点可以归结为与用户交互,第三点是实时的任务提醒,同时第三点也会与用户交互。
Notification 的基本操作
Notification 的基本操作主要有创建、更新、取消这三种。一个 Notification 的必要属性有三项,如果不设置则在运行时会抛出异常:
1. 小图标,通过 setSmallIcon() 方法设置
2. 标题,通过 setContentTitle() 方法设置
3. 内容,通过 setContentText() 方法设置
除了以上三项,其它均为可选项。虽然如此,但还是应该给 Notification 设置一个 Action ,这样就可以直接跳转到 App 的某个 Activity 、启动一个 Service 或者发送一个 Broadcast。否则,Notification 仅仅只能起到通知的效果,而不能与用户交互。
当系统接收到通知时,可以通过震动、响铃、呼吸灯等多种方式进行提醒.关于 setSmallIcon() 与 setLargeIcon()。在 NotificationCompat.Builder 中有设置通知的大小图标的两个方法。这两个方法有什么区别呢?当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在通知的右下角, largeIcon 显示在左侧;当只设置 setSmallIcon() 时, smallIcon 显示在左侧。
代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final String NOTIFICATION_TAG = "littlejie";
private int updataIndex = 0;
private int clearIndex = 0;
private Button ClickMe1;
private Button ClickMe2;
private Button ClickMe3;
private Button ClickMe4;
private Button ClickMe5;
private Button ClickMe6;
private Button ClickMe7;
private Button ClickMe8;
private Button ClickMe9;
private Button ClickMe10;
private Button ClickMe11;
//获取 NotificationManager 实例
private NotificationManager mNotificationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//NotificationManager 实例不能创建在onCreate之前
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
private void initView() {
ClickMe1 = (Button) findViewById(R.id.ClickMe1);
ClickMe1.setOnClickListener(this);
ClickMe2 = (Button) findViewById(R.id.ClickMe2);
ClickMe2.setOnClickListener(this);
ClickMe3 = (Button) findViewById(R.id.ClickMe3);
ClickMe3.setOnClickListener(this);
ClickMe4 = (Button) findViewById(R.id.ClickMe4);
ClickMe4.setOnClickListener(this);
ClickMe5 = (Button) findViewById(R.id.ClickMe5);
ClickMe5.setOnClickListener(this);
ClickMe6 = (Button) findViewById(R.id.ClickMe6);
ClickMe6.setOnClickListener(this);
ClickMe7 = (Button) findViewById(R.id.ClickMe7);
ClickMe7.setOnClickListener(this);
ClickMe8 = (Button) findViewById(R.id.ClickMe8);
ClickMe8.setOnClickListener(this);
ClickMe9 = (Button) findViewById(R.id.ClickMe9);
ClickMe9.setOnClickListener(this);
ClickMe10 = (Button) findViewById(R.id.ClickMe10);
ClickMe10.setOnClickListener(this);
ClickMe11 = (Button) findViewById(R.id.ClickMe11);
ClickMe11.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ClickMe1:
ShowNotification();
break;
case R.id.ClickMe2:
ShowLargeIconNotification();
break;
case R.id.ClickMe3:
ShowNotificationWithTag();
break;
case R.id.ClickMe4:
ShowIntentNotification();
break;
case R.id.ClickMe5:
ShowUpdata1Notification();
break;
case R.id.ClickMe6:
ShowTenNotifications();
break;
case R.id.ClickMe7:
ShowFlagNoClearNotification();
break;
case R.id.ClickMe8:
ShowFlagAutoCancelNotification();
break;
case R.id.ClickMe9:
ShowFlagOngoingEventNotification();
break;
/**
* 取消 Notification
* 取消通知有如下 5 种方式:
* 点击通知栏的清除按钮,会清除所有可清除的通知
* 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL 的通知,点击该通知时会清除它
* 通过 NotificationManager 调用 cancel(int id) 方法清除指定 ID 的通知
* 通过 NotificationManager 调用 cancel(String tag, int id) 方法清除指定 TAG 和 ID 的通知
* 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知
*
* 如果你是通过 NotificationManager.notify(String tag, int id, Notification notify) 方法创建的通知,
* 那么只能通过 NotificationManager.cancel(String tag, int id) 方法才能清除对应的通知,
* 调用NotificationManager.cancel(int id) 无效。
* */
case R.id.ClickMe10:
clearIndex += 1;
if (clearIndex == 5) {
clearIndex = 10;
}
if (clearIndex == 20) {
clearIndex = 1;
}
mNotificationManager.cancel(clearIndex);
break;
case R.id.ClickMe11:
mNotificationManager.cancel(NOTIFICATION_TAG, 3);
break;
}
}
/**
* 最简单的Notification
* Notification 的创建主要涉及到 Notification.Builder,Notification,NotificationManager.
* Notification.Builer : 使用建造者模式构建 Notification 对象。
* Notification : 通知对应类,保存通知相关的数据。NotificationManager 向系统发送通知时会用到。
* NotificationManager : NotificationManager 是通知管理类,它是一个系统服务。调用 NotificationManager 的 notify() 方法可以向系统发送通知。
*/
private void ShowNotification() {
/*
创建一个Notification主要有一下三个步骤
1.获取 NotificationManager 实例
2.实例化 NotificationCompat.Builder 并设置相关属性
3.通过 builder.build() 方法生成 Notification 对象,并发送通知
*/
//实例化NotificationCompat.Builde并设置相关属性
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.box)
.setContentTitle("Title is a test")
.setContentText("Text is a test");
//通过builder.build()方法生成Notification对象,并发送通知,第一个参数:id=1
mNotificationManager.notify(1, builder.build());
}
/**
* 设置大图标
*/
private void ShowLargeIconNotification() {
Resources res = MainActivity.this.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.book_open)
//设置大图标
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.bank))
.setContentTitle("Title is a LargeIcon test")
.setContentText("Text is a LargeIcon test");
mNotificationManager.notify(2, builder.build());
}
/**
* 使用notify(String tag, int id, Notification notification)方法发送通知
* 移除对应通知需使用 cancel(String tag, int id)
*/
private void ShowNotificationWithTag() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Send Notification With Tag")
.setContentText("Hi,My id is 1,tag is " + NOTIFICATION_TAG);
mNotificationManager.notify(NOTIFICATION_TAG, 3, builder.build());
}
/**
* 给 Notification 设置 Action,让Notification可以跳转,点击可清除
*/
private void ShowIntentNotification() {
//获取PendingIntent
Intent mainIntent = new Intent(this, MainActivity.class);
//四个参数分别是:context,requestCode,intent,flag
/*
PendingIntent 是一种特殊的 Intent ,字面意思可以解释为延迟的 Intent ,用于在某个事件结束后执行特定的 Action 。
从上面带 Action 的通知也能验证这一点,当用户点击通知时,才会执行。
PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用)。
也就是说,即便创建该PendingIntent对象的进程被杀死了,这个PendingItent对象在其他进程中还是可用的。
PendingIntent 主要可以通过以下三种方式获取:
//获取一个用于启动 Activity 的 PendingIntent 对象
public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags);
//获取一个用于启动 Service 的 PendingIntent 对象
public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags);
//获取一个用于向 BroadcastReceiver 广播的 PendingIntent 对象
public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
PendingIntent 的第四个参数flag的种类:
FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的 PendingIntent 对象,
那么就将先将已有的 PendingIntent 取消,然后重新生成一个 PendingIntent 对象。
FLAG_NO_CREATE:如果当前系统中不存在相同的 PendingIntent 对象,系统将不会创建该 PendingIntent 对象
而是直接返回 null 。
FLAG_ONE_SHOT:该 PendingIntent 只作用一次。
FLAG_UPDATE_CURRENT:如果系统中已存在该 PendingIntent 对象,那么系统将保留该 PendingIntent 对象,
但是会使用新的 Intent 来更新之前 PendingIntent 中的 Intent 对象数据,例如更新 Intent 中的 Extras 。
*/
PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Resources res = MainActivity.this.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.battery)
//设置大图标
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.button_add))
.setContentTitle("Title is a can Intent test")
.setContentText("Text is a can Intent test")
//点击通知后自动清除
.setAutoCancel(true)
//设置跳转
.setContentIntent(mainPendingIntent);
mNotificationManager.notify(4, builder.build());
}
/**
* 更新 Notification
* 更新通知很简单,只需要再次发送相同 ID 的通知即可,如果之前的通知还未被取消,则会直接更新该通知相关的属性;
* 如果之前的通知已经被取消,则会重新创建一个新通知。
*/
private void ShowUpdata1Notification() {
updataIndex += 1;
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.box)
.setContentTitle("Title Have Updata : " + updataIndex)
.setContentText("Text Have Updata : " + updataIndex);
//更新的时候,这里要传相应的ID
mNotificationManager.notify(1, builder.build());
}
/**
* 循环发送十个通知
*/
private void ShowTenNotifications() {
for (int i = 10; i < 20; i++) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Send Notification Batch")
.setContentText("Hi,My id is " + i);
mNotificationManager.notify(i, builder.build());
}
}
/**
* 设置FLAG_NO_CLEAR
* 该 flag 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除
* Notification.flags属性可以通过 |= 运算叠加效果
*/
private void ShowFlagNoClearNotification() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Send Notification Use FLAG_NO_CLEAR")
.setContentText("Hi,My id is 1,i can't be clear.");
Notification notification = builder.build();
//设置 Notification 的 flags = FLAG_NO_CLEAR
//FLAG_NO_CLEAR 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除
//flags 可以通过 |= 运算叠加效果
notification.flags |= Notification.FLAG_NO_CLEAR;
mNotificationManager.notify(5, notification);
}
/**
* 设置FLAG_AUTO_CANCEL
* 该 flag 表示用户单击通知后自动消失
*/
private void ShowFlagAutoCancelNotification() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//设置一个Intent,不然点击通知不会自动消失
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Send Notification Use FLAG_AUTO_CLEAR")
.setContentText("Hi,My id is 1,i can be clear.")
.setContentIntent(resultPendingIntent);
Notification notification = builder.build();
//设置 Notification 的 flags = FLAG_NO_CLEAR
//FLAG_AUTO_CANCEL 表示该通知能被状态栏的清除按钮给清除掉
//等价于 builder.setAutoCancel(true);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(6, notification);
}
/**
* 设置FLAG_ONGOING_EVENT
* 该 flag 表示发起正在运行事件(活动中)
*/
private void ShowFlagOngoingEventNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Send Notification Use FLAG_ONGOING_EVENT")
.setContentText("Hi,My id is 1,i can't be clear.");
Notification notification = builder.build();
//设置 Notification 的 flags = FLAG_NO_CLEAR
//FLAG_ONGOING_EVENT 表示该通知通知放置在正在运行,不能被手动清除,但能通过 cancel() 方法清除
//等价于 builder.setOngoing(true);
notification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(7, notification);
}
}
带进度条的Notification
private void ShowProgressBarNotification() {
count++;
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("带进度条的")
.setContentText("神奇吧.")
.setProgress(100, count, false);
mNotification = builder.build();
mNotificationManager.notify(8, mNotification);
}
Runnable run = new Runnable() {
@Override
public void run() {
Log.e("11111", "run");
ShowProgressBarNotification();
if (count < 100) {
handler.postDelayed(run, 200);
}
}
};
需要在上面添加:
private Notification mNotification; private int count = 0; private Handler handler = new Handler();在点击的时候:
ShowProgressBarNotification(); handler.post(run);
设置 Notification 的通知效果
前面讲了 Notification 的创建、更新和取消,以及给 Notification 设置 Action 等基本操作。那么,我怎么给 Notification 设置诸如震动、铃声、呼吸灯等效果呢?别急,接下来马上就会告诉你怎么给 Notification 添加效果。
Notification 有震动、响铃、呼吸灯三种响铃效果,可以通过 setDefaults(int defualts)
方法来设置。 Default 属性有以下四种,一旦设置了 Default 效果,自定义的效果就会失效。
除了以上几种设置 Notification 默认通知效果,还可以通过以下几种 FLAG 设置通知效果。
/**
* 铃声效果的通知
* 补充:使用系统自带的铃声效果:Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
*/
private void showRingNotifyWith() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("我是伴有铃声效果的通知")
.setContentText("美妙么?安静听~")
//调用系统默认响铃,设置此属性后setSound()会无效
.setDefaults(Notification.DEFAULT_SOUND);
//调用系统多媒体裤内的铃声
//.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"));
//调用自己提供的铃声,位于 /res/values/raw 目录下
//.setSound(Uri.parse("android.resource://com.littlejie.notification/" + R.raw.sound));
//另一种设置铃声的方法
//Notification notify = builder.build();
//调用系统默认铃声
//notify.defaults = Notification.DEFAULT_SOUND;
//调用自己提供的铃声
//notify.sound = Uri.parse("android.resource://com.littlejie.notification/"+R.raw.sound);
//调用系统自带的铃声
//notify.sound = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2");
//mManager.notify(2,notify);
Notification notify = builder.build();
//无限循环
//notify.flags |= Notification.FLAG_INSISTENT;
mNotificationManager.notify(9, notify);
}
/**
* 展示有震动效果的通知,需要在AndroidManifest.xml中申请震动权限
* <uses-permission android:name="android.permission.VIBRATE" />
* 补充:测试震动的时候,手机的模式一定要调成铃声+震动模式,否则你是感受不到震动的
*/
private void showNotifyWithVibrate() {
//震动也有两种设置方法,与设置铃声一样,在此不再赘述
long[] vibrate = new long[]{0, 500, 1000, 1500};
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("我是伴有震动效果的通知")
.setContentText("颤抖吧,凡人~")
//使用系统默认的震动参数,会与自定义的冲突
//.setDefaults(Notification.DEFAULT_VIBRATE)
//自定义震动效果
.setVibrate(vibrate);
//另一种设置震动的方法
//Notification notify = builder.build();
//调用系统默认震动
//notify.defaults = Notification.DEFAULT_VIBRATE;
//调用自己设置的震动
//notify.vibrate = vibrate;
//mNotificationManager.notify(9,notify);
mNotificationManager.notify(9, builder.build());
}
/**
* 通知无限循环,直到用户取消或者打开通知栏(其实触摸就可以了),效果与FLAG_ONLY_ALERT_ONCE相反
* 注:这里没有给Notification设置PendingIntent,也就是说该通知无法响应,所以只能手动取消
*/
private void showInsistentNotify() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("我是一个死循环,除非你取消或者响应")
.setContentText("啦啦啦~")
.setDefaults(Notification.DEFAULT_ALL);
Notification notify = builder.build();
notify.flags |= Notification.FLAG_INSISTENT;
mNotificationManager.notify(6, notify);
}