Android、ReactNative、Flutter集成Firebase推送注意事项

简介

涉及Android原生、ReactNative版本、Flutter集成Flirebase推送遇到的问题,以及一些注意事项。今年几个项目都采用了Firebase推送,有AndroidX版本,也有不是AndroidX的版本,需要根据项目选择合适的版本。本文不是从头教你配置Firebase,建议先看官方文档,这里是汇总一下注意事项和可能出错的情况。

各开发语言官方文档汇总

Firebase的推送功能,在官方叫Firebase cloud-messaging云信息传递 (简称FCM)

Android原生

React-Native

3.3.x5.2.x5.4.x5.5.x5.6.x
React Native0.50-520.52-58^0.59.3^0.59.3- ^0.61x0.60+
Play Services Android SDK11.8.0 +^16.1.0^16.1.0^16.1.0 (or ^17.x via jetifier)same as 5.5.x
Firebase iOS SDK4.7.0 +^5.10.x - ^5.18.x^5.19.x - ^5.20.x^5.19.x - ^6.x6.13+

Flutter

Firebase版本查询

2019-06-17发布了新版本,从这个版本开始,各个Firebase功能库支持AndroidX,如果不想使用AndroidX版本,需要2019-06-17之前的库版本。

Firebase中的每个功能包都有很多版本,以下可以查询可用的版本号

引入关键

建议先看官方文档,这里只列举一些关键操作,并不是完整操作流程。

Android原生

  1. 装库,build.gradle配置
    /android/app/build.gradle
apply plugin: 'com.android.application'
...
apply plugin: 'com.google.gms.google-services' // <- Add this line,这个一定要放在所有的apply plugin中最下面, 或者直接添加到文件的底部。
implementation 'com.google.firebase:firebase-iid:20.2.4'
    implementation 'com.google.firebase:firebase-messaging:20.2.4'

最好直接参照 Firebase官方提供的原生demo 查看/messaging目录下的项目

ReactNative

RN0.60以下的版本

不支持AndroidX的版本,不能使用太高的版本。

  1. 先装库
npm install react-native-firebase
react-native link react-native-firebase
  1. 配置/android/app/build.gradle
apply plugin: 'com.android.application'
...
apply plugin: 'com.google.gms.google-services' // <- Add this line,这个一定要放在所有的apply plugin中最下面,或者直接添加到文件的底部。
implementation "com.google.firebase:firebase-core:16.0.9"
    implementation "com.google.android.gms:play-services-base:16.1.0"
    implementation "com.google.firebase:firebase-messaging:18.0.0"
    implementation "com.google.firebase:firebase-auth:17.0.0"

RN0.60以上版本

这是支持AndroidX的库

  1. 装库
# Using npm
npm install --save @react-native-firebase/app
npm install --save @react-native-firebase/messaging

# Using Yarn
yarn add @react-native-firebase/app
yarn add @react-native-firebase/messaging
  1. 配置/android/app/build.gradle
apply plugin: 'com.android.application'
...
apply plugin: 'com.google.gms.google-services' // <- Add this line,这个一定要放在所有的apply plugin中最下面 

以下都不需要了,如果添加了可以移除:
implementation “com.google.firebase:firebase-core:16.0.9”
implementation “com.google.android.gms:play-services-base:16.1.0”
implementation “com.google.firebase:firebase-messaging:18.0.0”
implementation “com.google.firebase:firebase-auth:17.0.0”

Flutter

目前环境信息:

Flutter 1.20.2 • channel unknown • unknown source
Framework • revision bbfbf1770c (7 weeks ago)2020-08-13 08:33:09 -0700
Engine • revision 9d5b21729f
Tools • Dart 2.9.1
  1. Flutter装库
    在pubspec.yaml文件中添加:
dependencies:
  firebase_messaging: ^7.0.2
  firebase_core: ^0.5.0
  1. 配置/android/app/build.gradle
apply plugin: 'com.android.application'
...
apply plugin: 'com.google.gms.google-services' // <- Add this line,这个一定要放在所有的apply plugin中最下面 
implementation 'com.google.firebase:firebase-messaging:20.2.4'
    implementation 'com.google.firebase:firebase-iid:20.2.4'
    implementation 'com.google.firebase:firebase-auth:19.4.0'

消息类型

FCM 消息简介

有两种类型:

  • 通知消息,有时被称为“显示消息”。此类消息由 FCM SDK 自动处理。由系统通知栏显示。
  • 数据消息,无法直接在ui层显示,由客户端应用处理。
使用情景如何发送
通知消息推送到系统通知栏显示设置 notification 键,也可以设置 data 键
数据消息客户端应用负责处理数据消息,也叫消息负载仅设置 data 键

通知消息格式

token仅做示例用途
当app处于后台,notification中的内容会显示在通知栏上。

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
  }
}

数据消息格式

token仅做示例用途

data键里的内容表示 消息负载

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    }
  }
}

总结:

  1. 应用在前台,不会自动弹出通知栏。可以自己实现,先创建通知栏通道,再接收到消息后显示自定义通知栏。
  2. 应用在后台,会弹出系统通知栏。

包含可选数据载荷的通知消息

  • 在后台运行时,应用会在通知面板中接收通知有效负载,且仅在用户点按通知时处理数据有效负载。
  • 在前台运行时,您的应用将会接收一个消息对象,且两种载荷都可用,表示可以收到这两种数据。
{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    },
    "data" : {
      "Nick" : "Mario",
      "Room" : "PortugalVSDenmark"
    }
  }
}

处理消息

在 Android 应用中接收消息
接收消息,请使用继承 FirebaseMessagingService 的服务。您的服务应该重写 onMessageReceived 和 onDeletedMessages 回调方法。

不管是Android原生、React-Native、Flutter都需要设置继承 FirebaseMessagingService 的服务,重写onMessageReceived来接受推送过来的消息。

只不过React-Native和Flutter插件都自动帮我们做好了监听服务,不需要手动在AndroidManifest.xml文件中添加

<service
            android:name=".java.MyFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

配置接收推送消息

  • 当应用在后台或被杀死时送达的通知消息。在这种情况下,通知将传送至设备的系统任务栏。默认情况下,用户点按通知即可打开应用启动器。

  • 在后台所接收的同时具备通知和数据载荷的消息。 在这种情况下,通知将传送至设备的系统任务栏,数据载荷则传送至启动器 Activity 的 intent 的 extras 属性中。

Firebase有两种消息类型,通知类型和数据类型。

应用状态通知数据两者皆有(通知类型和数据类型)
前台onMessageReceivedonMessageReceivedonMessageReceived回调数据,但不会不出系统通知栏
后台系统通知栏onMessageReceived通知:出现系统通知栏
数据:intent 的 extras 属性中

实际使用中,大多数会使用两者皆有的情况,包含通知和数据类型

  • 当应用在前台的时候,会回调onMessageReceived方法。
  • 当应用在后台的时候,会显示出通知栏, 但不会回调onMessageReceived方法。然后点击后,通过intent 的 extras 可以获取携带的数据类型。

配置接收通知和数据类型

  1. 重写FirebaseMessagingService中的onMessageReceived方法,注意在这个方法的主线程中处理任务不能超过10秒,否则会引起ANR。
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // 获取data数据类型中的数据
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
    }

    // 获取notification中的内容
    if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    }
}
  1. 当应用在后台,显示系统通知栏,点击获取其中的data数据。

先给Activity配置启动模式,可以给主Activity设置。

	<activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask" // 添加这一行,设置启动模式
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

在MainActivity中重写

public class MainActivity extends AppCompatActivity {
	@Override
    protected void onCreate(Bundle savedInstanceState) {
   		// 当应用第一次启动,比如应用在没启动的情况下,收到Firebase推送,点击进来可以获取到里面携带的data参数。
    	if (getIntent().getExtras() != null) {
            for (String key : getIntent().getExtras().keySet()) {
                Object value = getIntent().getExtras().get(key);
                Log.d(TAG, "Key: " + key + " Value: " + value);
            }
        }
    }
    
	@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // 由于前面设置了启动模式,当应用在后台时,收到Firebase推送,点击进来可以会走onNewIntent回调,获取到里面携带的data参数。
        Bundle bundle = intent.getExtras();
        if(bundle != null){
            for(String key: bundle.keySet()){
                Object value = bundle.get(key);
                Log.i(TAG, "key = " + key + " value = " + value);
            }
        }

    }
}

Flutter的接收消息实现

Flutter的库不仅实现了FirebaseMessagingService,还实现了FlutterFirebaseMessagingReceiver来接收数据,观察源码发现FlutterFirebaseMessagingService中的onMessageReceived方法为空,主要依靠FlutterFirebaseMessagingReceiver

//AndroidManifest.xml配置内容
<service android:name=".FlutterFirebaseMessagingService"
      android:exported="false">
      <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
      </intent-filter>
    </service>
    
<receiver
      android:name=".FlutterFirebaseMessagingReceiver"
      android:exported="true"
      android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
      </intent-filter>
    </receiver>

测试推送消息

打开Firebase后台控制器,发送到指定的token设备。token的获取可以参考官方demo。
在这里插入图片描述
这里的设置只是notification通知类型,即推送的格式如下:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"请问"
      "body":"测试"
    }
  }
}

可以通过以下方法添加数据类型。
在这里插入图片描述
这样就是一条 通知+数据类型 的推送消息,即推送的格式如下:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"请问"
      "body":"测试"
    },
     "data" : {
      "name" : "SuperBin"
    }
  }
}

Flutter配置

当应用在后台,收到推送来的消息,点击notification,想要回调onResume方法,需要添加数据click_action: FLUTTER_NOTIFICATION_CLICK。

在这里插入图片描述

接收推送消息的关键

  1. 在Android P(8.0) 或更高版本,打开设置中“电池”,将应用设置成“不被优化”等。官方文档说明

后台受限应用(Android P(8.0) 或更高版本),接触限制 从 2019 年 1 月开始,FCM
将不会向由用户置于后台限制的应用传送消息(例如,通过“设置”->“应用和通知”->“[appname]”->“电池”)

  1. 优先选择三星手机,或者带有google服务的国产手机,要记得打开服务,而且国产手机的app被杀死后,由于国产系统的定制化会断开Firebase的连接,无法在收到推送消息。
  2. 在国内使用,打开vpn。
  3. 允许应用弹出通知栏。
  4. 通过firebase库的getToken()方法,获取的token值,跟app是绑定的,那app启每次启动,getToken()获取的值是不变的。在重新安装应用或deleteToken()等清除token的操作后,才会获取到新的token值。
  5. 应用放在后台,但不能杀死。
  6. 查看控制台是否有出现Firebase相关的错误。
  7. 重启手机或模拟器。

相关问题

通知渠道

  • 官方文档-通知渠道
    从 Android 8.0(API 级别 26)开始,必须为所有通知分配渠道,否则通知将不会显示。
    可以参考Flutter库实现,先构建android的消息通道,再自定义显示通知栏。

1. Flutter中集成出现

PluginRegistry cannot be converted to FlutterEngine类型转换问题

2. Flutter集成出现,应用在后台,点击通知栏推送的消息Notification,无法回调onResume方法

在标题"Flutter配置",就有讲解问题,点击跳转阅读

3. 获取到Token但无法收到推送消息

  1. 先按 接收推送消息的关键 的流程排查以下步骤。
  2. 如果以上都没问题,还无法收到,则大部分是Firebase后台配置的问题,可以考虑不用Firebase的推送测试功能,直接跟公司的后台对接试试。
  3. 看一下配置/android/app/build.gradle,com.google.gms.google-services是不是在所有的apply plugin中最下面
apply plugin: 'com.android.application'
...
apply plugin: 'com.google.gms.google-services' // <- Add this line,这个一定要放在所有的apply plugin中最下面 
  1. 也可以考虑修改google-services版本信息,比如官方目前最新推荐是4.3.4,可以改成4.3.0或其他版本。
// classpath 'com.google.gms:google-services:4.3.4'
classpath 'com.google.gms:google-services:4.3.0'
  1. 在Firebase控制台,查看一下是否出现同包名的情况,如果存在两个不同项目下,有相同的包名,则Firebase后台检测的时间会比较久。尽量不要在不同项目中,使用相同的包名。
    在这里插入图片描述

在这里插入图片描述
这一步会很慢很慢,可以直接跳过,正在验证中的应用会在右侧显示一个图标,如下图所示。根据我的测试,我在一个项目中创建了两个应用,左边的应用没有图标,表示验证通过,能稳定收到推送。但有右边的应用,处于验证状态,现象就比较难预计,如果能收到推送就说明走通流程了,就不用管这个图标了。但有可能会出现,能获取到token但无法收到推送,再按上面的流程排查一下。
在这里插入图片描述

4.报错Service not registered:

还没仔细研究,并不影响消息的推送

java.lang.IllegalArgumentException: Service not registered: com.google.android.gms.measurement.internal.zzjn@4fb2406

相关链接

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值