赞
踩
今天在做通知的模块。才知道8.0及其以上的系统通知的创建已经不是简单的用 NoticeficationCompat.Builder就可以创建出来的。8.0系统引入了一个消息通道概念----- NotificationChannel。
所以我们需要创建通知的时候,判断下是否是8的系统。以下是完整代码
- //1:获取系统提供的通知管理服务
- notificationManager = (NotificationManager)
- getSystemService(Context.NOTIFICATION_SERVICE);
- //2:如果是8以上的系统,则新建一个消息通道
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- setChannerl();
- }
- private void setChannerl() {
-
- channelId = "chat";//消息通道的id,以后可以通过该id找到该消息通道
- String channelName = "聊天消息";//消息通道的name
- int importance = NotificationManager.IMPORTANCE_MAX;//通知的优先级
- // .具体的请自行百度。作用就是优先级的不同。可以导致消息出现的形式不一样。
- // MAX是会震动并且出现在屏幕的上方。设置优先级为low或者min时。来通知时都不会震动,
- // 且不会直接出现在屏幕上方
- createNotificationChannel(channelId, channelName, importance);
- }
- @TargetApi(Build.VERSION_CODES.O)
- private void createNotificationChannel( String channelId, String channelName,
- int
- importance) {
- NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
- notificationManager.createNotificationChannel(channel);
- }
然后我是点击按钮来模拟收到通知:
- findViewById(R.id.btn_send).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- //3:创建通知
- createNotification("测试通知");
- }
- });
-
private void createNotification( String content) { Intent intent = new Intent(this, SecondActivity.class); /* * 调用PendingIntent的静态放法创建一个 PendingIntent对象用于点击通知之后执行的操作, * PendingIntent可以理解为延时的Intent,在这里即为点击通知之后执行的Intent * 这里调用getActivity(Context context, int requestCode, Intent intent, int flag)方法 * 表示这个PendingIntent对象启动的是Activity,类似的还有getService方法、getBroadcast方法 */ PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0); NotificationCompat.Builder builder; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //如果是8以上的系统。需要传一个channelId. builder = new NotificationCompat.Builder(this, "chat"); } else { builder = new NotificationCompat.Builder(this); } builder .setContentTitle("通知1") // 创建通知的标题 .setContentText(content) // 创建通知的内容 .setSmallIcon(R.drawable.ic_launcher_background) // 创建通知的小图标 .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) // 创建通知的大图标 /* * 首先,无论你是使用自定义视图还是系统提供的视图,上面4的属性一定要设置,不然这个通知显示不出来 */ .setWhen(System.currentTimeMillis()) // 设定通知显示的时间 .setContentIntent(pi) // 设定点击通知之后启动的内容,这个内容由方法中的参数:PendingIntent对象决定 //.setPriority(NotificationCompat.PRIORITY_MAX) // 设置通知的优先级 .setAutoCancel(true); // 设置点击通知之后通知是否消失 //.setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg"))) // 设置声音 /* * 设置震动,用一个 long 的数组来表示震动状态,这里表示的是先震动1秒、静止1秒、再震动1秒,这里以毫秒为单位 * 如果要设置先震动1秒,然后停止0.5秒,再震动2秒则可设置数组为:long[]{1000, 500, 2000}。 * 别忘了在AndroidManifest配置文件中申请震动的权限 */
builder.setVibrate(new long[]{1000, 500, 2000});
/* * 设置手机的LED灯为蓝色并且灯亮2秒,熄灭1秒,达到灯闪烁的效果,不过这些效果在模拟器上是看不到的, * 需要将程序安装在真机上才能看到对应效果,如果不想设置这些通知提示效果, * 可以直接设置:setDefaults(Notification.DEFAULT_ALL); * 意味将通知的提示效果设置为系统的默认提示效果 */ //.setLights(Color.BLUE, 2000, 1000) Notification notification = builder.build(); // 创建通知(每个通知必须要调用这个方法来创建) /* * 使用从系统服务获得的通知管理器发送通知,第一个参数是通知的id,不同的通知应该有不同的id, * 这样当我们要取消哪条通知的时候我们调用notificationManager(通知管理器).cancel(int id) * 方法并传入发送通知时的对应id就可以了。在这里如果我们要取消这条通知, * 我们调用notificationManager.cancel(1);就可以了 * 第二个参数是要发送的通知对象 */ notificationManager.notify(1, notification);
到此。就创建出来一个通知了。我们可以在8.0以上的手机找到设置--》应用和通知---》应用信息---》找到你的那个应用---》应用通知就可以看到会有个类别。这里面的列表就是我们在应用里面创建的应用通道。你可以点击通道查看详情。
点击运行,我们可以看到通知可以正常的弹出来。可是对比一下就可以看到。在8以下的系统上。消息的震动我们是可以控制的。以前我们只要把:
builder.setVibrate(new long[]{1000, 500, 2000});
修改成
builder.setVibrate(new long[]{0});
就可以不震动了。可是这个方法在8.0的设备上并没有起作用。写了以后还是会震动。最后通过查看资料发现。8.0以后。消息的震动就不再是修改builder就可以的。我们需要修改消息通道的属性,代码如下:
@TargetApi(Build.VERSION_CODES.O) private void createNotificationChannel(boolean isVibrate, String channelId, String channelName, int importance) { NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); //NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); if (isVibrate) { // 设置通知出现时的震动(如果 android 设备支持的话) channel.enableVibration(true); channel.setVibrationPattern(pattern); } else { // 设置通知出现时不震动 channel.enableVibration(false); channel.setVibrationPattern(new long[]{0}); } notificationManager.createNotificationChannel(channel); }
8.0以下的还是
builder.setVibrate(new long[]{0});
即可。
然后我又发现一个问题。就是channel一旦createNotificationChannel出来以后。你通过代码再去修改他的属性就不再起作用。
因为我界面上有个checkBox。我想实现。勾选以后接受通知的时候就是震动的。不勾选就是不震动的。
刚开始的思路是在cb的setOnCheckedChangeListener方法里面。去修改channel的enableVibration和setVibrationPattern两个属性的值。发现没有任何作用。后来我思考是不是。因为。channel一旦生产出来就是在系统里面了。不能修改了。于是我又在修改之前。根据channelId先去查看查找有没有。如果有。
notificationManager.deleteNotificationChannel(channelId);
我就先删除掉。然后我再重新new.并且create.即代码修改成了:
- cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
-
- setChannerl(b);
- Log.e("zmm", "onCheckedChanged------------>" + b);
- }
- });
- private void setChannerl(boolean checked) {
-
- channelId = "chat";//消息通道的id,以后可以通过该id找到该消息通道
- String channelName = "聊天消息";//消息通道的name
- int importance = NotificationManager.IMPORTANCE_MAX;//通知的优先级
- // .具体的请自行百度。作用就是优先级的不同。可以导致消息出现的形式不一样。
- // MAX是会震动并且出现在屏幕的上方。设置优先级为low或者min时。来通知时都不会震动,
- // 且不会直接出现在屏幕上方
- createNotificationChannel(checked, channelId, channelName, importance);
- }
@TargetApi(Build.VERSION_CODES.O) private void createNotificationChannel(boolean isVibrate, String channelId, String channelName, int importance) { //先删除之前的channelId对应的消息通道. notificationManager.deleteNotificationChannel(channelId); //重新new一个消息通道。 NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); //是否震动 if (isVibrate) { // 设置通知出现时的震动(如果 android 设备支持的话) channel.enableVibration(true); channel.setVibrationPattern(pattern); } else { // 设置通知出现时不震动 channel.enableVibration(false); channel.setVibrationPattern(new long[]{0}); } notificationManager.createNotificationChannel(channel); }
删除app.然后重新运行。我第一次进来。发消息是没有震动的。正确。然后勾选cb。然后重新点击发送通知。结果通知是接受到了。可是没有震动。。。。气人不!!!气人。。。
仔细看了下。代码。确定不是因为我自己的粗心哪里写错了。那就是我用的哪个方法肯定没有作用。
经过一杯茶的冷静。我在思考会不会是channelId的原因。因为虽然我删除掉了 。但是系统会不会是像一般的后台一样是个假删除。然后再用相同的id去new的时候。系统又把之前的消息通道拿出来了。如果是这样的话。那属性是没办法修改的。为了测试。我把channelId修改成动态的了。我每次勾选cb的时候。i++。然后channelid="chat"+i;为了防止越来越多的channel.我用beforeId记录之前的channelId。然后再新建的时候。先去删除beforeId.然后再新建。代码如下:
- cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
- i++;
- setChannerl(b);
- Log.e("zmm", "onCheckedChanged------------>" + b);
- }
- });
- private void setChannerl(boolean checked) {
-
- channelId = "chat" + i;//消息通道的id,以后可以通过该id找到该消息通道
- String channelName = "聊天消息" + i;//消息通道的name
- int importance = NotificationManager.IMPORTANCE_MAX;//通知的优先级
- // .具体的请自行百度。作用就是优先级的不同。可以导致消息出现的形式不一样。
- // MAX是会震动并且出现在屏幕的上方。设置优先级为low或者min时。来通知时都不会震动,
- // 且不会直接出现在屏幕上方
- createNotificationChannel(checked, channelId, channelName, importance);
- beforeChannelId = channelId;
- }
@TargetApi(Build.VERSION_CODES.O) private void createNotificationChannel(boolean isVibrate, String channelId, String channelName, int importance) { if (!TextUtils.isEmpty(beforeChannelId)) { //先删除之前的channelId对应的消息通道. notificationManager.deleteNotificationChannel(beforeChannelId); } //重新new一个消息通道。 NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); //是否震动 if (isVibrate) { // 设置通知出现时的震动(如果 android 设备支持的话) channel.enableVibration(true); channel.setVibrationPattern(pattern); } else { // 设置通知出现时不震动 channel.enableVibration(false); channel.setVibrationPattern(new long[]{0}); } notificationManager.createNotificationChannel(channel); }
别忘了修改createNotification()方法里面的
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder = new NotificationCompat.Builder(this, channelId);//该处写的应该是当前的channelId。 } else { builder = new NotificationCompat.Builder(this); }
然后重新运行。第一次。发通知。没有震动。OK的。勾选震动。发通知。震动了。OK的!
至此问题就解决了。为了一探究竟。想看下deleteNotificationChannel源码的实现。发现我没有下载源码。所以看不了。于是去官方文档看了下。
。英语不好就不翻译了。但是还是能看到的。如果你新建的channel和要删除的channel是同一个channelId的话。新建的channel的属性和要删除的那个channel是相同的。。。。。我境界还没达到。不知道这样设计的目的。但是应该有他们的原因。。。
重点1:8.0以上消息震动是通过修改channel来实现的:
if (isVibrate) { // 设置通知出现时的震动(如果 android 设备支持的话) channel.enableVibration(true); channel.setVibrationPattern(pattern); } else { // 设置通知出现时不震动 channel.enableVibration(false); channel.setVibrationPattern(new long[]{0}); }
重点2:channel一旦被create出来。修改属性没有作用,可以通过删除掉。再重新create。但是要记得要删除的channelId和要新建的channelId不能一致.
我也好久没写博客了。。之前一个月。忙着交接工作。辞职。搬家。找工作。好在。一切都再慢慢步入正轨。从一个城市到另一个城市。说后悔谈不上。不舍却有的。只是在想。是不是当初可以有更好的选择。不过回到合肥以后。确定开心了很多。在这个城市。有很多我熟悉的朋友。还有一个待我很好的朋友。总是去她家蹭饭。而且一次噩梦也没有做过。离家也近了很多。而且。在这里。我不会觉得害怕。不会觉得孤单。虽然。新公司里面我还不熟悉。但是大家看着就是很好的人。我应该可以和他们好好好相处。。最后但愿我在新公司里面可以多学点东西。嗯。接下来的日子请继续加油!!!
每日语录:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。