概述
上节实现消息通知栏并通过点击消息传递数据跳转页面。消息是App 向用户发送的信息通知机制,它的显示位置包括状态栏、通知栏、锁屏。如微信消息、系统消息等。
上节嘟宝创建的默认消息,是无法像微信上部弹出消息,而是被收录在不重要消息内容里。app发布消息需要分成三步
- 创建一个通道,名为channel,该通道被系统记录,可在app中设置通道参数
- 创建多个消息,共享一个通道。消息需指明通道id,消息标题内容
- 发布消息
封装消息类
右键com.zilong.dubao>New> Java Class
NotificationMsg源码
package com.zilong.dubao;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import androidx.core.app.NotificationCompat;
public class NotificationMsg {
private String channelID="DUBAO";
private String channelName="嘟宝安心守护孩子安全";
private Context context;
private NotificationManager manager=null;
private int id=1000;
NotificationMsg(Context context){
this.context=context;
}
private void createNotificationChannel() {
manager =(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
public void sendNotification(String title,String content) {
if (manager==null){
createNotificationChannel();
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelID)
.setSmallIcon(R.drawable.logo)
.setContentTitle(title)
.setContentText(content);
manager.notify(id, builder.build());
id++;
}
public void sendNotification(String title, String content, Intent intent) {
if (manager==null){
createNotificationChannel();
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, id, intent, PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelID)
.setSmallIcon(R.drawable.logo)
.setContentIntent(pendingIntent)
.setContentTitle(title)
.setContentText(content);
manager.notify(id, builder.build());
id++;
}
}
MainActivity源码
package com.zilong.dubao;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
NotificationMsg notificationMsg=new NotificationMsg(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initBtn();
}
private void initBtn(){
Button button =findViewById(R.id.sendmsg);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MessageActivity.class);
intent.putExtra("name","嘟妈101");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationMsg.sendNotification("来自嘟妈的消息","快起床出去玩了",intent);
}
});
}
}
运行效果如下:
点击按钮发送消息,通知栏不提示有消息,也未有声音与震动。这并非发送消息源码有问题。消息等级均为默认设置。消息等级设置有两处
- 一在创建通道对消息等级统一设置,默认是有声音,无震动(默认行为),普通通知
- 二在创建消息时设置消息等级,默认是图片通知。 Android app关于消息通知的设置,在应用程序详情中有两处,不同手机略有不同: 路径:应用设置 > 应用管理 > 嘟宝>通知管理
- 通知过滤规则,有Andorid 系统自动判断消息显示规则
- 通知类别,专为通道chanel消息设置
Android 通道优先级
重要性级别 值 行为表现 使用场景
IMPORTANCE_NONE 0 完全不显示,被静默拦截 禁用通知
IMPORTANCE_MIN 1 只显示在通知栏底部,无声音、无震动、无弹出 不重要的后台信息
IMPORTANCE_LOW 2 显示在通知栏,无声音、无震动 低优先级信息
IMPORTANCE_DEFAULT 3 有声音,无震动(默认行为) 普通通知
IMPORTANCE_HIGH 4 有声音、有震动,可能弹出横幅 重要消息
IMPORTANCE_MAX 5 最高优先级(已废弃,等同于 HIGH) 紧急通知
NotificationCompat 提供了以下几种优先级:
优先级 常量 说明
最大 PRIORITY_MAX 最高优先级,可能弹出 Heads-up
高 PRIORITY_HIGH 高优先级,声音/横幅提醒
默认 PRIORITY_DEFAULT 普通通知
低 PRIORITY_LOW 不重要,减少打扰
最低 PRIORITY_MIN 几乎隐藏
无 PRIORITY_NONE 不显示提醒
以下为系统默认设置
而后,将过滤规则改为
全部设为重要,将悬浮通知权限打开。测试结果如下:
嘟宝接收绑定信令
嘟宝通过mqtt在后台与服务器 长久连接,嘟妈通过信令与嘟宝交互数据,建立音视频通信。
- 嘟妈与嘟宝的第一次通信,应从扫描二维码开始。两者交互流程如下:
- 嘟宝app启动,显示二维码,并启动前台服务建立MQTT连接,订阅主题/dubao/dubaoID
- 嘟妈扫描二维码,向嘟宝发送绑定指令
- 嘟宝收到绑定指令后,通知栏消息手动确认绑定,发送确认指令给嘟妈
- 存储绑定信息 当MQTT收到嘟妈的绑定信令时,app发出消息通知栏,引导用户绑定。 嘟宝与嘟妈通信数据格式,选择JSON。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用“键值对”结构来组织数据,具有体积小、可读性强、跨平台等特点,被广泛用于客户端与服务器之间的数据传输。Android、Java、PHP、Python、Web 等开发中都会大量使用 JSON 来存储和交换数据,例如接口返回、配置文件、网络通信等场景。
{"code":"bind","dumaName":"嘟妈","dumaId":"f1122aeb-f2b0-400d-9919-eddd2eaebaa2","dubaoId":"11122aeb-f2b0-400d-9919-eddd2eaeb1f2"}
上述json,code功能指令,dumaName为嘟妈名称,dumaId、dubaoId为嘟宝嘟妈的身份识别码。这是一条嘟妈发送嘟宝请求绑定的信息。嘟宝收到该条信息后,手动确认完成绑定。
json解析
嘟宝通过mqtt接收到是一系列json字符串,然后再将json字符串解析成基本类型数据。Android解析json字符串有两种方式,
- 一是原生JSONObject
- 二是通过Gson 解析(实际开发最常用) Gson 是 Google 推出的一个 Java JSON 解析库,用于将Java对象 与 JSON 字符串之间的相互转换。
引入Gson库
入下图:
点击Sync now,下载同步到工程
Gson解析事例
MainActivity源码
package com.zilong.dubao;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initBtn();
}
private void initBtn(){
Button button =findViewById(R.id.sendmsg);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
parseJson();
}
});
}
class Msg{
String code;
String dumaName;
String dumaId;
String dubaoId;
}
private void parseJson(){
String json="{\"code\":\"bind\",\"dumaName\":\"嘟妈\",\"dumaId\":\"f1122aeb-f2b0-400d-9919-eddd2eaebaa2\",\"dubaoId\":\"cfb20ccc-8c53-4434-85bb-a171c3ca7c0c\"}";
Gson gson = new Gson();
Msg msg = gson.fromJson(json, Msg.class);
((TextView)findViewById(R.id.code)).setText(msg.code);
((TextView)findViewById(R.id.dumaName)).setText(msg.dumaName);
((TextView)findViewById(R.id.dumaId)).setText(msg.dumaId);
((TextView)findViewById(R.id.dubaoId)).setText(msg.dubaoId);
}
}
activity_main源码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/code"
android:text="未有数据"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/dumaName"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/dumaId"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/dubaoId"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/sendmsg"
android:text="解析"
android:layout_width="match_parent"
android:layout_height="100dp"/>
</LinearLayout>
运行结果