转载地址:Notification常见样式总结
转载:https://stackoverflow.com/questions/38016215/android-notificationmanagercompat-arenotificationsenabled-not-working/39486721
转载:https://www.jianshu.com/p/92afa56aee05
转载:Android开发——Notification通知的使用及NotificationCopat.Builder常用设置API
参考地址:Android Oreo 通知新特性,这坑老夫先踩了
参考地址:Android:检查通知权限并跳转到通知设置界面
参考地址:PendingIntent总结
private void toNotification(Context context) {
if (context == null) {
LogUtils.w(TAG, "toNotification context = null");
return;
}
//support应至少为24,compileSdkVersion必须为24
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
if (areNotificationsEnabled) {
LogUtils.i(TAG, "拥有通知的权限");
Intent clickIntent = new Intent(); //点击通知之后要发送的广播
int id = (int) (System.currentTimeMillis() / 1000);
clickIntent.setAction(ACTION_NOTIFY_CLICKED_MESSAGE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), id, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "channelId" + System.currentTimeMillis();
NotificationChannel channel = new NotificationChannel(channelId, context.getResources().getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.setStyle(new NotificationCompat.BigTextStyle().bigText("不普通的内容," +
"不普通的内容,不普通的内容,不普通的内容,不普通的内容,"));
// .setBigContentTitle("不普通的标题头,不普通的标题头不普通的标题头不普通的标题头不普通的标题头")
}
builder
.setContentTitle("这个是个PT长度的TITLE")
// .setContentText("这个是个PT长度的CONTENT")
.setDefaults(NotificationCompat.FLAG_AUTO_CANCEL)
.setAutoCancel(true)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
.setSmallIcon(R.mipmap.ic_launcher)
.setGroupSummary(false)// 强制设置不要折叠
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis());
manager.notify(1, builder.build());
} else {
LogUtils.w(TAG, "没有通知的权限");
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notify);
ButterKnife.bind(this);
notificationReceiver = new NotificationReceiver();
IntentFilter filter3 = new IntentFilter();
filter3.addAction(ACTION_NOTIFY_CLICKED_MESSAGE);
registerReceiver(notificationReceiver, filter3);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(notificationReceiver);
}
public class NotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
LogUtils.i(TAG, "onReceive");
if (intent != null && ACTION_NOTIFY_CLICKED_MESSAGE.equals(intent.getAction())) {
LogUtils.i(TAG, "onReceive ACTION_NOTIFY_CLICKED_MESSAGE");
}
}
}
前两个图是vivo X20A上的效果图,第三个效果是HUAWEI P30
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
转载:https://stackoverflow.com/questions/38016215/android-notificationmanagercompat-arenotificationsenabled-not-working/39486721
需要判断通知显示的方法可用,需要:
android {
compileSdkVersion 24
}
dependencies {
compile 'com.android.support:support-v4:24.0.0'
}
以上。
注意:areNotificationsEnabled 只对 API 19 及以上版本有效,低于API 19 会一直返回true
如果打开通知显示,可以前往设置:
LogUtils.w(TAG, "没有通知的权限");
Intent intent = new Intent();
LogUtils.i(TAG, "通知权限未开启,手机信息 ==" + "\n" +
"手机型号" + android.os.Build.MODEL + "\n" +
"SDK版本" + android.os.Build.VERSION.SDK + "\n" +
"系统版本" + android.os.Build.VERSION.RELEASE + "\n" +
"软件包名" + getPackageName() + "\n"
);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LogUtils.i(TAG, "当前版本 API > 26");
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
intent.putExtra(Settings.EXTRA_CHANNEL_ID, getApplicationInfo().uid);
} else {
LogUtils.i(TAG, "当前版本 API < 26");
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.putExtra("app_package", getPackageName());
intent.putExtra("app_uid", getApplicationInfo().uid);
}
startActivity(intent);
} catch (Exception e) {
LogUtils.w(TAG, "当前版本跳转通知栏设置异常");
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
Intent clickIntent = new Intent(); //点击通知之后要发送的广播
int id = (int) (System.currentTimeMillis() / 1000);
clickIntent.setAction(ACTION_NOTIFY_CLICKED_MESSAGE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), id, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
.setContentIntent(pendingIntent)
PendingIntent的实例获取一般有以下五种方法:
getActivity()
getActivities()
getBroadcast()
getService()
getForegroundService()
常用的有三种:
getActivity
从系统取得一个用于启动一个Activity的PendingIntent对象
getBroadcast
从系统取得一个用于向BroadcastReceiver的Intent广播的PendingIntent对象
getService
从系统取得一个用于启动一个Service的PendingIntent对象
如上描述,PendingIntent 获取的方式有多种。但是几种获取方式的参数都是互通的,都是 Context context, int requestCode, Intent intent, int flags.
如果想理解PendingIntent的参数含义,首先得了解一下什么是相同的PendingIntent。
参考地址:PendingIntent总结
重点概念:
当PendingIntent中的Intent和requestCode都相同即说明这两个是相同的PendingIntent
当Intent的componentName和intent-filter都相同即说明这两个是相同的Intent
所以,requestCode的作用:
在有两个PendingIntent,并且两个PendingIntent的intent相同的情况下,控制PendingIntent是否相同。
理解reqCode:
场景默认是 flag = FLAG_UPDATE_CURRENT,intent相同:
分析场景1:1579
此时,推送通知到通知栏,一切ok
分析场景2:1579 后 2579
通知栏收到1579后,未点击;2579 通知到达通知栏。因为都是润滑油的变化,所以1579的点击后的操作,要被2579覆盖。requestCode 在这里表示操作5。
分析场景3:1579后2579,再3679。
场景2中描述后,3679,因为是汽油变化,所以不能刷新之前通知点击后的操作,所以汽油的requestCode区别于润滑油。6区别于5.
intent:调用意图
component :
作用 :component用于明确指定需要启动的目标组件
intent-filter:
作用:过滤Action、Category属性
优点:解耦
PendingIntent.FLAG_CANCEL_CURRENT
如果当前已存在则取消当前的并返回一个新的 PendingIntent
PendingIntent.FLAG_UPDATE_CURRENT
如果已存在则更新之前的
PendingIntent.FLAG_NO_CREATE
如果已存在则返回当前存在的,否则返回 null
PendingIntent.FLAG_ONE_SHOT
表明这个 PendingIntent 只能用一次,触发一次后自动 cancel
PendingIntent.FLAG_IMMUTABLE
表明这个PendingIntent 不可变
场景1:
requestCode 和 intent 相同,
clickIntent.putExtra(EXTRA_012, "content:" + EXTRA_012 +" "+ num);
manager.notify(num++, builder.build());
操作:
第一次通知发送后,不点击;第二次通知发送后,分别点击第一次和第二次。
结果:
第二次的通知中的extra值,会覆盖第一次通知的extra的值。
场景2:
修改场景1中的代码,修改requestCode可变:
和场景1相同的操作。
结果:
通知2,不会覆盖掉通知1中,extra的value
结论:FLAG_UPDATE_CURRENT 在 PendingIntent 相同的条件下,会覆盖Extra的value值
场景3:
requestCode 和 intent 相同,
clickIntent.putExtra(EXTRA_012, "content:" + EXTRA_012 +" "+ num);
manager.notify(num++, builder.build());
操作:
第一次通知发送后,不点击;第二次通知发送后,分别点击第一次和第二次。
结果:
通知1,点击后,有点击回馈,通知栏会关闭,但是不会执行PendingIntent 动作;
通知2,点击后会正常执行动作。
场景4:
修改requestCode为可变。
此时PendingIntent 互不相同,不会产生影响,会都正常执行动作。
结论:FLAG_CANCEL_CURRENT在 PendingIntent 相同的条件下,点击有回馈,但是会取消上个通知PendingIntent 执行
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "channelId" + System.currentTimeMillis();
NotificationChannel channel =
new NotificationChannel(channelId, context.getResources().getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
转载:https://www.jianshu.com/p/92afa56aee05
Android O 引入了 通知渠道(Notification Channels),以提供统一的系统来帮助用户管理通知,如果是针对 android O 为目标平台时,必须实现一个或者多个通知渠道,以向用户显示通知。若并不以 Android O 为目标平台,当应用运行在 android O 设备上时,其行为将与运行在 Android 7.0 上时相同。
作用:开发者可以为需要发送的每个不同的通知类型创建一个通知渠道
所以,上面代码会有问题,因为channelId 每次都会随机创建一个,导致应用每发送一次推送,即会创建一个渠道。
如图 手机的通知管理中:
左图中,通知类别会和发送通知的次数一样多…
右图是类别详情,每种类别详情都可以由用户自由设置。
修改代码:
String channelId = "channelId1212" + "123456789";
String channelId13 = "channelId1313" + "123456789";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (requestCode == 1212) {
NotificationChannel channel = new NotificationChannel(channelId, "普通推送", NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder.setChannelId(channelId);
} else if (requestCode == 1313) {
NotificationChannel channel = new NotificationChannel(channelId13, "重要通道", NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder.setChannelId(channelId13);
}
}
示例图:
参考地址:Android Oreo 通知新特性,这坑老夫先踩了
包含:
声音
光
振动
在锁屏上显示
替换免打扰模式
NotificationChannel channel = new NotificationChannel(channelId, "普通推送", NotificationManager.IMPORTANCE_HIGH);
String description = "这是一个普通推送的渠道描述";
channel.setDescription(description);
// 设置通知出现时的闪灯(如果 android 设备支持的话)
channel.enableLights(true);
channel.setLightColor(Color.RED);
// 设置通知出现时的震动(如果 android 设备支持的话)
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
// 覆盖勿扰设置(无法更改)
channel.setBypassDnd(true);
// 屏幕锁定时通知显示方式(无法更改)
/*
* @hide
*@IntDef(prefix = {"VISIBILITY_"}, value = {
*VISIBILITY_PUBLIC,
*VISIBILITY_PRIVATE,
*VISIBILITY_SECRET,
*})
*/
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
//其中“lockscreenVisibility”和“setBypassDnd”是无法生效的,因为从源码中来看,只能被系统或排序服务(Android Notification Ranking Service)更改。
manager.createNotificationChannel(channel);
builder.setChannelId(channelId);
Oreo不用Priority了,用importance,importance包含以下:
修改上面代码:
// 通知渠道组的id.
String groupId = "渠道组ID001";
// 用户可见的通知渠道组名称.
CharSequence groupName = "渠道组名字001";
NotificationChannel channel = new NotificationChannel(channelId, "普通推送", NotificationManager.IMPORTANCE_HIGH);
NotificationChannelGroup group = new NotificationChannelGroup(groupId, groupName);
channel.setGroup(groupId);
manager.createNotificationChannelGroup(group);
manager.createNotificationChannel(channel);
builder.setChannelId(channelId);
加入渠道组,是如下代码:
NotificationChannelGroup group = new NotificationChannelGroup(groupId, groupName);
channel.setGroup(groupId);
manager.createNotificationChannelGroup(group);
示意图:
注意:上面示意图是 vivo X20A 上的截图;在HUAWEI P30上不能显示出类别来,不知道怎么搞
代码转载自:Notification常见样式总结
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.setStyle(new NotificationCompat.BigTextStyle().bigText("不普通的内容," +
"不普通的内容,不普通的内容,不普通的内容,不普通的内容,"));
// .setBigContentTitle("不普通的标题头,不普通的标题头不普通的标题头不普通的标题头不普通的标题头")
}
Android 系统和机型影响比较大啊,在HUAWEI P30系统中,如下代码和示意图:
//Ticker是状态栏显示的提示
builder.setTicker("简单Notification");
//第一行内容 通常作为通知栏标题
builder.setContentTitle("标题");
//第二行内容 通常是通知正文
builder.setContentText("通知内容");
//第三行内容 通常是内容摘要什么的 在低版本机器上不一定显示
builder.setSubText("这里显示的是通知第三行内容!");
//ContentInfo 在通知的右侧 时间的下面 用来展示一些其他信息
builder.setContentInfo("2");
//number设计用来显示同种通知的数量和ContentInfo的位置一样,如果设置了ContentInfo则number会被隐藏
// builder.setNumber(2);
//系统状态栏显示的小图标
builder.setSmallIcon(R.mipmap.ic_launcher);
效果图:
这几行,
builder.setTicker("简单Notification");
builder.setContentInfo("2");
没有效果。
在HUAWEI P30系统中,如下代码和示意图:
builder.setContentTitle("BigTextStyle");
builder.setContentText("BigTextStyle演示示例");
builder.setSmallIcon(R.mipmap.ic_launcher);
android.support.v4.app.NotificationCompat.BigTextStyle style = new android.support.v4.app.NotificationCompat.BigTextStyle();
style.bigText("这里是点击通知后要显示的正文,可以换行可以显示很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长");
style.setBigContentTitle("点击后的标题");
//SummaryText没什么用 可以不设置
style.setSummaryText("总结");
builder.setStyle(style);
效果图:
没有效果的是:
builder.setContentText("BigTextStyle演示示例");
builder.setContentTitle("InboxStyle");
builder.setContentText("InboxStyle演示示例");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_a));
android.support.v4.app.NotificationCompat.InboxStyle style = new android.support.v4.app.NotificationCompat.InboxStyle();
style.setBigContentTitle("BigContentTitle")
.addLine("第一行,第一行,第一行,第一行,第一行,第一行,第一行")
.addLine("第二行")
.addLine("第三行")
.addLine("第四行")
.addLine("第五行")
.addLine("第6行")
.setSummaryText("SummaryText");
builder.setStyle(style);
效果:
这里
builder.setContentText("InboxStyle演示示例");
就好用?
效果:
显示大图:
就最大的那个图。
builder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(BitmapFactory.decodeResource(context.getResources(), R.drawable.navi_marker_current)));
显示边图:
角标下面的图标,不知道怎么形容那个位置的图片,随便叫吧!
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_a));
int progress = 43;
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_a));
//禁止用户点击删除按钮删除
builder.setAutoCancel(false);
//禁止滑动删除
builder.setOngoing(true);
//取消右上角的时间显示
builder.setShowWhen(false);
builder.setContentTitle("下载中..." + progress + "%");
builder.setProgress(100, progress, false);
builder.setContentIntent(pendingIntent);
需要注意:manager.notify(num++, builder.build()); 第一次参数代表通知栏ID,如果是进度条,需要在原ID上更新,而不是弹出新的通知,ID应该是定值。
测试 HUAWEI P30,横幅正常,同时通知栏内也会有这次通知。
builder.setContentTitle("横幅通知");
builder.setContentText("请在设置通知管理中开启消息横幅提醒权限");
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_a));
//这句是重点
builder.setFullScreenIntent(pendingIntent,false);
builder.setAutoCancel(true);
效果:
横幅不点击或者划走(上划取消),会一致存在。
如果点击,横幅和通知栏内的通知都会消失;如果划走,通知栏内的通知还会存在。
NotificationCompat.Builder自动设置的默认值:
priority: PRIORITY_DEFAULT //通知的重要程度
when: System.currentTimeMillis() //时间
audio stream: STREAM_DEFAULT //音效 系统默认音效
setAutoCancel(boolean autocancel)
setContent(RemoteView view)
setContentTitle(String string)
setContentText(String string)
setContentIntent(PendingIntent intent)
setWhen(long when)
Notification.PRIORITY_MAX 重要而紧急的通知,通知用户这个事件是时间上紧迫的或者需要立即处理的。
Notification.PRIORITY_HIGH 高优先级用于重要的通信内容,例如短消息或者聊天,这些都是对用户来说比较有兴趣的
Notification.PRIORITY_DEFAULT 默认优先级用于没有特殊优先级分类的通知
Notification.PRIORITY_LOW 低优先级可以通知用户但又不是很紧急的事件。只显示状态栏图标
Notification.PRIORITY_MIN 用于后台消息 (例如天气或者位置信息)。只有用户下拉通知抽屉才能看到内容
setPriority(int pri)
setStyle(Style style)
setVisibility(int visibility)
Notification.DEFAULT_SOUND 添加默认声音提醒
Notification.DEFAULT_VIBRATE 添加默认震动提醒
Notification.DEFAULT_LIGHTS 添加默认呼吸灯提醒
Notification.DEFAULT_ALL 同时添加以上三种默认提醒
setDefault(int defaults)
setLight(int argb, int onMs, int offMs)
setSound(Uri sound)
setVibrate(long [] pattern)
setCategory(String category)
setColor(int argb)
setFullScreenIntent(PendingIntent intent,boolean b)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
.setGroupSummary(false)
.setSubText("这是通知的次要内容");
setContentInfo 在 api 24 被废弃,不再显示,用 setSubText 代替
setNumber 在 api 24 被废弃,不再显示
// 附加文本
builder.setContentInfo("INFO");
// 附加数字,等价于 setContentInfo, 为了显示效果用一个不同的字体尺寸显示数字
builder.setNumber(123);
.setShowWhen(false);
.setProgress(max, progress, indeterminate);
在 api 21 后不再显示
.setTicker("this is ticker");
.setOnlyAlertOnce(true);
.setDeleteIntent(pi);
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
如果已经发送过相同id的通知,新通知会替换掉原来的通知。
manager.notify(id, builder.build());
manager.cancel (int id)
manager.cancelAll ()
manager.notify(String tag ,int id, Notification notification)
manager.cancel(String tag, int id)
manager.createNotificationChannel(channel);
manager.createNotificationChannelGroup(new NotificationChannelGroup(groupId, groupName));
三个参数分别为渠道ID,渠道名字,渠道重要度
NotificationChannel(String id,CharSequence name, int importance)
channel.setGroup("测试组ID");
channel.setDescription(description);
channel.enableLights(true);
channel.setLightColor(Color.RED);
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
channel.setBypassDnd(true);
VISIBILITY_PUBLIC,
VISIBILITY_PRIVATE,
VISIBILITY_SECRET,
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);