消息渠道
Google为什么要引入消息渠道这个,因为在之前版本的Android通知管理中,通知消息要么全部接收,要么全部屏蔽,然而消息渠道改变了这一特点。
就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。
以小米手机上的微信为例
API介绍
不带 channelId 已被废弃,慎用!!!
当然,Google也并没有完全做绝,即使方法标为了废弃,但还是可以正常使用的。可是如果你将项目中的targetSdkVersion指定到了26或者更高,那么Android系统就会认为你的App已经做好了8.0系统的适配工作,当然包括了通知栏的适配。这个时候如果还不使用通知渠道的话,那么你的App的通知将完全无法弹出。因此这里给大家的建议就是,一定要适配。
创建通知渠道
package com.wust.notifydemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initNotificationChannel();
}
/**
* 初始化消息渠道
*/
private void initNotificationChannel() {
// 要确保的是当前手机的系统版本必须是Android 8.0系统或者更高,
// 因为低版本的手机系统并没有通知渠道这个功能,
// 不做系统版本检查的话会在低版本手机上造成崩溃。
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
// 创建一个通知渠道至少需要渠道ID、渠道名称以及重要等级这三个参数
// 渠道ID可以随便定义,只要保证全局唯一性就可以
String channelId = "chat";
// 渠道名称是给用户看的,需要能够表达清楚这个渠道的用途
String channelName = "聊天消息";
// 重要等级的不同则会决定通知的不同行为,重要等级还可以设置为IMPORTANCE_LOW、IMPORTANCE_MIN,分别对应了更低的通知重要程度。
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
channelId = "subscribe";
channelName = "订阅消息";
importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
}
}
@TargetApi(Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importance) {
// 创建 channel
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
// 获取 notificationManager
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 注册 channel
notificationManager.createNotificationChannel(channel);
}
}
运行代码,可以在 对应应用的 应用信息 =》 通知管理 =》 通知类别下看到我们创建的两个 channel ,效果如下:
刚才我们创建的两个通知渠道这里已经显示出来了。可以看到,由于这两个通知渠道的重要等级不同,通知的行为也是不同的,聊天消息可以发出提示音并在屏幕上弹出通知,而订阅消息只能发出提示音。
当然,用户还可以点击进去对该通知渠道进行任意的修改,比如降低聊天消息的重要等级,甚至是可以完全关闭该渠道的通知。
至于创建通知渠道的这部分代码,你可以写在MainActivity中,也可以写在Application中,实际上可以写在程序的任何位置,只需要保证在通知弹出之前调用就可以了。并且创建通知渠道的代码只在第一次执行的时候才会创建,以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。
发送通知
触发通知的代码和之前版本基本是没有任何区别的,只是在构建通知对象的时候,需要多传入一个通知渠道ID,表示这条通知是属于哪个渠道的。
- 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_send_chat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送聊天消息"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_send_subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送订阅消息"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_send_chat" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 发送消息逻辑
btn_send_chat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//第一步:获取 NotificationManager
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//第二步:创建
Notification notification = new NotificationCompat.Builder(MainActivity.this, "chat")
.setContentTitle("收到一条聊天消息")
.setContentText("在干嘛呢?")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.bb)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bb))
.setAutoCancel(true)
.build();
//第三步:发送
notificationManager.notify(1, notification);
}
});
btn_send_subscribe.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//第一步:获取 NotificationManager
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//第二步:创建
Notification notification = new NotificationCompat.Builder(MainActivity.this, "subscribe")
.setContentTitle("收到一条订阅消息")
.setContentText("你买的彩票中了2个亿?")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.bb)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bb))
.setAutoCancel(true)
.build();
//第三步:发送
notificationManager.notify(2, notification);
}
});
管理通知渠道
btn_send_chat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//第一步:获取 NotificationManager
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//第四步:检测 "chat" 这个通道的消息等级
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
NotificationChannel channel = notificationManager.getNotificationChannel("chat");
if (channel.getImportance() != NotificationManager.IMPORTANCE_HIGH) {
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel.getId());
startActivity(intent);
Toast.makeText(MainActivity.this, "请手动将通知打开", Toast.LENGTH_SHORT).show();
}
}
//第二步:创建
Notification notification = new NotificationCompat.Builder(MainActivity.this, "chat")
.setContentTitle("收到一条聊天消息")
.setContentText("在干嘛呢?")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.bb)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bb))
.setAutoCancel(true)
.build();
//第三步:发送
notificationManager.notify(1, notification);
}
});
测试条件:你将 聊天消息 重要程度 手动设置为 低,当你点击发送聊天消息的时候,代码会引导你设置聊天消息等级
显示未读角标
修改两个地方
第一是在创建通知渠道的时候,调用了NotificationChannel的setShowBadge(true)方法,表示允许这个渠道下的通知显示角标。第二是在创建通知的时候,调用了setNumber()方法,并传入未读消息的数量。