Android Nofication详解(包括8.0适配)
通知栏的作用
通知栏的主要目的就是将一些重要的信息即使告诉用户,通知栏的设计非常巧妙,不用占用空间,只是在通知栏显示,当用户下拉就可以看到了,如果用户设置了通知的程度为最高的话,当受到消息会在当前界面显示内容(时间为2秒),之后就会隐藏到通知栏中。
为什么要是适配通知栏?
用于现在手机技术的发展,通知栏已经不再是我们以前见到的通知栏了,各个App为了抢占通知栏的空间,想要将自己的产品推荐给用户,将各种推送消息推送给用户,一段时间不看的话,用户的通知栏就会特别臃肿,已经全部都是各个App推送的消息了。
用户如何自己关闭/开启推送开关?
设置—>应用—>找到这个应用之后,里面有个通知,可以看到各种推送的消息,将自己需要的推送打开就可以了,一些垃圾信息,可以通过关闭来进行拦截。
通知栏适配
这里主要的分水岭是8.0(targetSdkVersion=26),在8.0以下的话我们可以在应用中找到显示通知,来进行关闭,这样的话所有的推送我们都收不到(包括一些重要的信息),所以8.0之后google新增了通知渠道,就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。拥有了这些控制权之后,用户就再也不用害怕那些垃圾推送消息的打扰了,因为用户可以自主地选择自己关心哪些通知、不关心哪些通知。
8.0以上通知栏(1).jpg 8.0以上通知栏(2).jpg 8.0以下通知栏(1).png对于每个App来说,通知渠道的划分是非常需要仔细考究的,因为通知渠道一旦创建之后就不能再修改了,因此开发者需要仔细分析自己的App一共有哪些类型的通知,然后再去创建相应的通知渠道。这里我们来参考一下ProjectDemo(自己的demo)的通知渠道划分:
这里可以明显看出来8.0以上通知渠道区分的很明确,用户可以根据自己的喜好,将需要的通知打开就可以了
这里先来说下8.0以前的Notification的写法
//1、通过获取NotificationManager实例来进行对通知进行管理
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//2、由于Android每个版本都对APi有不同的修改,为了兼容所有版本的API 采用v4包下边的NotificationCompat来创建Notification对象
NotificationCompat.Builder notification= new NotificationCompat.Builder(this);
//2、通过PendingIntent方法来进行点击通知进行的操作
/**
* Context context, int requestCode,@NonNull Intent intent, @Flags int flags, @Nullable Bundle options
* 上下文,1,inttent对象,flag,bundle
*/
Intent intent = new Intent(this, ServiceActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
//4、设置一些属性
notification
.setContentTitle(title)//设置标题
//设置style如果文字内容过多显示省略号之后可以用样式来显示全
//.setStyle(new NotificationCompat.BigTextStyle().bigText(""))
.setContentText(content)//设置内容
.setWhen(System.currentTimeMillis())//被创建的时间,毫秒为单位
.setSmallIcon(R.mipmap.ic_launcher) //设置小图标
//这里通过style来设置大图
// .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))).setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))//设置大图标
.setAutoCancel(true) //是否自动消失,true表示响应点击之后自动消失。
// .setSound(Uri.fromFile(new File("")))//这里用来传入音频文件的url
.setVibrate(new long[]{0, 1000, 1000, 1000})//设置震动,注意这里需要在AndroidManifest.xml中设置
//<!-- 声明手机震动权限 -->
// <uses-permission android:name="android.permission.VIBRATE" />
.setLights(Color.BLUE, 1000, 1000)//设置LED闪烁
// .setDefaults(NotificationCompat.DEFAULT_ALL)//根据手机环境播放铃声
//设置通知的重要程度
/**
* NotificationCompat.PRIORITY_MIN 最低程度
* NotificationCompat.PRIORITY_LOW 较低程度
* NotificationCompat.PRIORITY_DEFAULT 默认程度相当于不设置
* NotificationCompat.PRIORITY_HIGH 较高程度
* NotificationCompat.PRIORITY_MAX 最高程度
*/
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)//点击通知进行操作
.build();
//5、最后通过manager.notify将通知发送出去
manager.notify(1, notification);
8.0适配(不适配会怎样呢)
如果不进行适配的话,如果你的应用在8.0或者更高的版本上通知是接受不到了,google这次也算很强硬的,已经做出一些对应的策略。
开发者进行8.0(O)进行通知栏的适配 如果你的targetSdkVersion>=26 那么恭喜你的 你需要进行8.0通知栏适配,不然用户是收不到你的通知信息。
8.0通知栏适配效果:用户可以根据自己想要收到的通知,在设置里面找到应用来进行通知的关闭和打开
注意:这里必须区分8.0以后和8.0之前的区别 不然在低版本的手机上会出现崩溃的现象
/**
* 这里需要创建一个通知渠道其中必须包括
* 渠道id 这个可以随便定义,但是要保证全局的唯一性
* 渠道名称 这个是最直接最接近可以的 用来让用户知道渠道的用途
* 重要等级
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelId = "chat";
channelName = "聊天信息";
int importanceHigh = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importanceHigh);
channelId = "subscribe";
channelName = "订阅消息";
importanceHigh = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importanceHigh);
}
@TargetApi(Build.VERSION_CODES.O)
private Notification getChannelNotification(String title, String content, String channelId) {
Notification.Builder builder = new Notification.Builder(this, channelId);
return builder
.setContentTitle(title)
.setContentText(content)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setAutoCancel(true)
.setVibrate(new long[]{1000, 500, 2000})
.setLights(Color.BLUE, 2000, 1000)
.build();
}
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Notification notification = getChannelNotification("收到一条聊天信息", "这是聊天内容", "chat");
manager.notify(1, notification);
}
下面是自己的demo(可以直接复制)
这里将8.0上下综合到一起,大家可以稍作改动封装运用到自己的项目中
1、布局
<?xml version="1.0" encoding="utf-8"?>
<layout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.dongbo.demo.projectdemo.ui.NoficationActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendChatMsg"
android:text="发送聊天消息" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendSubscribeMsg"
android:text="发送订阅消息" />
</LinearLayout>
</layout>
2、Activity代码
package com.dongbo.demo.projectdemo.ui;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.databinding.DataBindingUtil;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import com.dongbo.demo.projectdemo.R;
import com.dongbo.demo.projectdemo.databinding.ActivityNoficationBinding;
public class NoficationActivity extends AppCompatActivity {
ActivityNoficationBinding binding;
private String channelId = "";
private String channelName = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_nofication);
iniView();
}
private void iniView() {
//判断当前版本是不是>=8.0
/**
* 由于现在所有的app应用都希望通过推送消息来进行自己app的宣传造成用户的通知栏非常的臃肿,有时候一晚上不看手机,第二天通知栏已经爆满了
* google已经根据这种情况做出了相应的对策
* 开发者进行8.0(O)进行通知栏的适配 如果你的targetSdkVersion>=26 那么恭喜你的 你需要进行8.0通知栏适配,不然用户是收不到你的通知信息
* 8.0通知栏适配效果:用户可以根据自己想要收到的通知,在设置里面找到应用来进行通知的关闭和打开
* 注意:这里必须区分8.0以后和8.0之前的区别 不然在低版本的手机上会出现崩溃的现象
* 这里需要创建一个通知渠道其中必须包括
* 渠道id 这个可以随便定义,但是要保证全局的唯一性
* 渠道名称 这个是最直接最接近可以的 用来让用户知道渠道的用途
* 重要等级
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelId = "chat";
channelName = "聊天信息";
int importanceHigh = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importanceHigh);
channelId = "subscribe";
channelName = "订阅消息";
importanceHigh = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importanceHigh);
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importanceHigh) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, importanceHigh);
channel.setShowBadge(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
private Notification getNotification_25(String title, String content) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
return builder.setContentTitle(title)
.setContentText(content)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setAutoCancel(true)
.build();
}
@TargetApi(Build.VERSION_CODES.O)
private Notification getChannelNotification(String title, String content, String channelId) {
Notification.Builder builder = new Notification.Builder(this, channelId);
return builder
.setContentTitle(title)
.setContentText(content)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setNumber(10)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setAutoCancel(true)
.setVibrate(new long[]{1000, 500, 2000})
.setLights(Color.BLUE, 2000, 1000)
.build();
}
public void sendChatMsg(View view) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Notification notification = getChannelNotification("收到一条聊天信息", "这是聊天内容", "chat");
manager.notify(1, notification);
} else {
Notification notification_25 = getNotification_25("收到一条聊天信息", "这是聊天内容");
manager.notify(1, notification_25);
}
}
public void sendSubscribeMsg(View view) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Notification notification = getChannelNotification("收到一条订阅消息", "这是订阅内容", "subscribe");
manager.notify(2, notification);
} else {
Notification notification_25 = getNotification_25("收到一条订阅消息", "这是订阅内容");
manager.notify(2, notification_25);
}
}
}
微信图片_20190804155450.jpg
微信图片_20190804154818.jpg
我demo中用的DataBinding如果大家想要运行可以将
DataBindingUtil.setContentView(this, R.layout.activity_nofication);
改成setContentView(R.layout.activity_nofication);然后将布局中最外面的<layout></layout>删掉就可以
或者在build中添加
dataBinding { enabled = true}就可以了
大家可以自己创建个应用去试验一下Notification效果
注意
8.0一下创建Notification对象是这样的
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
8.0以上是这样的
Notification.Builder builder = new Notification.Builder(this, channelId);
这里主要就是多了一个渠道号的参数
参考链接
郭霖老师的链接:
https://blog.csdn.net/guolin_blog/article/details/79854070