Notification的使用
实现通知步骤
一般实现通知需要如下步骤:
1.获取 NotificationManager 实例管理通知;
2.实例 Notification 对象;
3.管理事件 Intent;
4.发送通知。
注:如不需在通知出现时,点击时有事件执行,步骤3可以忽略。
普通通知
1.获取NotificationManager实例。
NotificationManager 对通知进行管理,调用 Context 的 getSystemService() 方法获取。
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
2.实例 Notification 对象。
Notification notification= new NotificationCompat.Builder(Context).build();
此时仅创建了一个对象,可在build()方法之前连缀多个方法设置通知属性。
Notification notification = new NotificationCompat.Builder(Context) .setContentText("通知内容") .setContentTitle("通知标题") .setSmallIcon(android.R.mipmap.ic_launcher_round) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_round)) .setWhen(System.currentTimeMillis()) .build();
setSmallIcon() 用于设置通知的小图标,只能使用纯 alpha 图层的图片进行设置,小图标会显示在系统状态栏上。(alpha 图层的图片你不知道没关系,UI 会知道的,哈哈,这个我也不知P出来,这里我只是暂时用默认图标代替)
setLargeIcon() 设置通知的大图标,当下拉通知后显示的图标。
setWhen() 指定通知被创建的时间,以毫秒为单位,下拉通知后会将时间显示在相应的通知上。
3.发送一条通知。
manager.notify(1,notification);
notify() 方法接收两个参数:
参数一:id ,指定通知的 id,要保证每个通知的 id 是不同的;
参数二:Notification 对象,传入之前创建好的即可。
当该通知显示出来后,点击是没有效果的,我们需要为它设置一个意图,跳转到我们需要的活动界面,这时,需要用到PendingIntent
PendingIntent 的获取 :可以根据需求选择getActivity(),getBroadcast(),getService() 等静态方法来获取。
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.baidu.com")); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0); Notification notification = new NotificationCompat.Builder(Content) .setContentIntent(pi) .build();
调用setContentIntent() 方法,传入 PendingIntent 实例即可,当点击同时会打开浏览器进入百度主页。
Nofication更多链式方法。
.setAutoCancel(true)//点击通知头自动取消 .setDefaults(NotificationCompat.DEFAULT_ALL)//设置铃声及震动效果等
也可对铃声,LED灯,震动等分别进行设置。
setSound()//铃声 setLights()//LED灯 setVibrate()//震动
注意:调用手机震动需要manifest文件中声明震动权限。
<uses-permission android:name="android.permission.VIBRATE"/>
悬挂式通知:
对于 Android 5.0(API 级别 21),当设备处于活动状态时(即,设备未锁定且其屏幕已打开),通知可以显示在小型浮动窗口中(也称为“浮动通知”)。 这些通知看上去类似于精简版的通知,只是浮动通知还显示操作按钮。 用户可以在不离开当前应用的情况下处理或清除浮动通知。
可能触发浮动通知的条件示例包括:
- 用户的 Activity 处于全屏模式中(应用使用
fullScreenIntent
),或者 - 通知具有较高的优先级并使用铃声或振动
//在 build()之前设置 .setFullScreenIntent() Notification builder = new NotificationCompat.Builder(Context); Notification notify = builder.setSmallIcon(R.mipmap.ic_launcher_round) .setPriority(Notification.PRIORITY_DEFAULT) //通知的优先级 .setCategory(Notification.CATEGORY_MESSAGE) //通知的类型 .setContentTitle("通知") .setAutoCancel(true) .setContentIntent(pi) .setContentText("Heads - Up Notification on Android 5.0") .setFullScreenIntent(pi, true) //不设置此项不会悬挂,false 不会出现悬挂 .build();
setPriority() 方法共有5个等级:
1. PRIORITY_MIN - 最低级别(-2);
2. PRIORITY_LOW - 较低级别(-1);
3. PRIORITY_DEFAULT - 默认级别(0);
4. PRIORITY_HIGH - 较高级别(1);
5. PRIORITY_MAX - 最高级别(2);
当发出此类型的通知时,通知会以悬挂的方法显示在屏幕上。
一般情况下,点击通知栏进入是一个新的Activity,而不是正在运行的Activity,如果我们需要点击通知的时候返回正在运行的活动,就可以在PendingIntent中设置一些方法了。
一般写法:
Intent notificationIntent = new Intent(this, MyActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);//PendingIntent获取的是活动 notification.contentIntent = contentIntent;//通知绑定 PendingIntent notification.flags=Notification.FLAG_AUTO_CANCEL;//设置自动取消 NotificationManager manager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(NOTIFY_ID, notification);
整改后的写法:
/ 设置启动的程序,如果存在则找出,否则新的启动 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setComponent(new ComponentName(this, MainActivity.class));//用ComponentName得到class对象 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);// 关键的一步,设置启动模式,两种情况 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);//将经过设置了的Intent绑定给PendingIntent notification.contentIntent = contentIntent;// 通知绑定 PendingIntent notification.flags=Notification.FLAG_AUTO_CANCEL;//设置自动取消 NotificationManager manager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(NOTIFY_ID, notification);
可能会出现悬挂式通知/普通通知不显示的情况,那是因为某些手机会关闭该通知(悬挂通知),我们可检查用户是否打开了通知,如果没有弹出对话框提示用户去设置中开启对话框。
if(!NotificationManagerCompat.from(this).areNotificationsEnabled()){ Log.e("tag","没有通知权限"); new AlertDialog.Builder(context) .setTitle("提示框") .setMessage("需要通知栏权限才能正常显示提示语与其他提醒,是否打开设置界面去设置?(建议开启,否则影响体验!)") .setPositiveButton("去设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 提醒用户跳转AppInfo页面,去打开App通知权限 Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", context.getPackageName(), null); intent.setData(uri); context.startActivity(intent); dialog.dismiss(); } }).setNegativeButton("取消", null).show();
折叠式通知:(未使用过)
折叠式同时需要借助 RemoteViews 来实现。
Notification builder = new NotificationCompat.Builder(Context); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.sina.com")); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0); // 未下拉的样式 R.layout.collapsed RemoteViews collapsed = new RemoteViews(getPackageName(), R.layout.collapsed); collapsed.setTextViewText(R.id.collapsed_text, "关闭状态"); //下拉后的样式R.layout.show RemoteViews show = new RemoteViews(getPackageName(), R.layout.show); Notification notify = builder.setAutoCancel(true) .setSmallIcon(R.mipmap.ic_launcher_round) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setContentIntent(pi) .setContentText("新浪微博") .setCustomContentView(collapsed)//下拉前 .setCustomBigContentView(show)//下拉后 .build(); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); manager.notify(0, notify);
锁屏通知
Android 5.0(API level 21)开始,通知可以显示在锁屏上,通过设置选择是否允许敏感的通知内容显示在安全的锁屏上。
//通过 setVisibility() 方法设置即可 ... .setVisibility(VISIBILITY_PUBLIC) .build();
setVisibility() 方法共有三个选值:
1.VISIBILITY_PRIVATE : 显示基本信息,如通知的图标,但隐藏通知的全部内容;
2.VISIBILITY_PUBLIC : 显示通知的全部内容;
3.VISIBILITY_SECRET : 不显示任何内容,包括图标。
通知的提醒方式
1、声音提醒
-
默认声音
notification.defaults |= Notification.DEFAULT_SOUND; -
自定义声音
notification.sound = Uri.parse(“file:///sdcard0/notification.ogg”);
2、震动提醒
-
默认振动
notification.defaults |= Notification.DEFAULT_VIBRATE; -
自定义振动
long[] vibrate = {100, 200, 300, 400}; //震动效果
// 表示在100、200、300、400这些时间点交替启动和关闭震动 notification.vibrate = vibrate;
3、闪烁提醒
- 默认闪烁
notification.defaults |= Notification.DEFAULT_LIGHTS;
- 自定义闪烁
notification.ledARGB = 0xff00ff00; // LED灯的颜色,绿灯
notification.ledOnMS = 300; // LED灯显示的毫秒数,300毫秒
notification.ledOffMS = 1000; // LED灯关闭的毫秒数,1000毫秒
notification.flags |= Notification.FLAG_SHOW_LIGHTS; // 必须加上这个标志
常见的Flags
-
FLAG_AUTO_CANCEL
当通知被用户点击之后会自动被清除(cancel) -
FLAG_INSISTENT
在用户响应之前会一直重复提醒音 -
FLAG_ONGOING_EVENT
表示正在运行的事件 -
FLAG_NO_CLEAR
通知栏点击“清除”按钮时,该通知将不会被清除 -
FLAG_FOREGROUND_SERVICE
表示当前服务是前台服务
Android 8.0 Notification:
private void showMessageNotification(Context context){ final int pushId = 1; NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE); NotificationCompat.Builder mBuilder; //判断是否是8.0Android.O if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //创建一个通知渠道(渠道id与渠道名) NotificationChannel chan1 = new NotificationChannel("渠道id", "渠道名", NotificationManager.IMPORTANCE_DEFAULT); chan1.setLightColor(Color.GREEN); chan1.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); mNotificationManager.createNotificationChannel(chan1); mBuilder = new NotificationCompat.Builder(context, "渠道id"); } else { mBuilder = new NotificationCompat.Builder(context,"渠道id"); } Intent notificationIntent = new Intent(context, MainActivity.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent intent = PendingIntent.getActivity(context, 0,notificationIntent, 0); mBuilder.setContentTitle("在线客服消息")//设置通知栏标题 .setContentText("内容")//设置通知栏内容 .setContentIntent(intent) //设置通知栏点击意图 .setNumber(1) //设置通知集合的数量 .setTicker("收到一条在线客服消息") //通知首次出现在通知栏,带上升动画效果的 .setWhen(System.currentTimeMillis())//通知产生的时间,会在通知信息里显示,一般是系统获取到的时间 .setDefaults(Notification.DEFAULT_ALL)//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合 .setSmallIcon(R.mipmap.ic_launcher);//设置通知小ICON Notification notify = mBuilder.build(); notify.flags |= Notification.FLAG_AUTO_CANCEL; mNotificationManager.notify(pushId, notify); }
Utils:
public class NotificationUtils {
private NotificationManager mManager;
private static class SingletonHolder {
private static final NotificationUtils INSTANCE = new NotificationUtils();
}
//获取单例
public static NotificationUtils getInstance() {
return SingletonHolder.INSTANCE;
}
public void createNotificationChannel(Context context, String channelId, String channelName) {
NotificationChannel channel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
getManager(context).createNotificationChannel(channel);
}
}
private NotificationManager getManager(Context context) {
if (mManager == null) {
mManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
}
return mManager;
}
public NotificationCompat.Builder getChannelNotification(Context context, String title, String content, PendingIntent pendingIntent, String channelId, boolean isFloating) {
if (isFloating) {
return new NotificationCompat.Builder(context, channelId)
.setAutoCancel(true)
.setPriority(NotificationManager.IMPORTANCE_DEFAULT)
.setSmallIcon(R.mipmap.icon_logo)
.setFullScreenIntent(pendingIntent, true)
.setContentTitle(title)
.setContentText(content);
} else {
return new NotificationCompat.Builder(context, channelId)
.setAutoCancel(true)
.setSmallIcon(R.mipmap.icon_logo)
.setContentIntent(pendingIntent)
.setContentTitle(title)
.setContentText(content);
}
}
public void sendNotification(Context context, String title, String content, PendingIntent pendingIntent, int notifyId, NotificationChannels channel, Boolean isFloating) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
createNotificationChannel(context, channel.channelId, channel.channelName);
Notification notification = getChannelNotification
(context, title, content,pendingIntent , channel.channelId, isFloating).build();
notification.contentIntent = pendingIntent;// 通知绑定 PendingIntent
getManager(context).notify(notifyId, notification);
} else {
Notification notification = getChannelNotification(context, title, content, pendingIntent, null, isFloating).build();
notification.contentIntent = pendingIntent;// 通知绑定 PendingIntent
getManager(context).notify(notifyId, notification);
}
}
public void cancelNotification(Context context, int notifyId) {
getManager(context).cancel(notifyId);
}
}
调用方式:
private void showNotifyWindow(String data, Context context) { Intent intent = new Intent(context, MainActivity.class); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent .FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP); String title = getString(R.string.congratulations); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationUtils.getInstance().sendNotification(this, title, data, pendingIntent, 0, NotificationChannels.BET_RESULT, true); }
参考博客:
https://blog.csdn.net/u012149399/article/details/49228069
https://blog.csdn.net/yxncl/article/details/72801230
https://blog.csdn.net/zhixuan322145/article/details/51277903