Hypertrack阻止Flutter中的FCM通知 [英] Hypertrack is preventing FCM notification in Flutter
问题描述
当我使用 hypertrack_plugin 以及 firebase_messaging ,我无法在Android中收到任何消息.但是,它在iOS中工作正常.
When I use hypertrack_plugin along with firebase_messaging in Flutter, I am not able to receive any message in Android. However, it works fine in iOS.
hypertrack_plugin的版本:0.1.3firebase_messaging版本:7.0.3
Version of hypertrack_plugin: 0.1.3 Version of firebase_messaging: 7.0.3
推荐答案
UPDATE
此问题已在 hypertrack_plugin 版本的插件更新中得到解决:0.1.4
This issue has been fixed in the plugin update which is in the version hypertrack_plugin: 0.1.4
问题
您正面临此问题,因为从 FirebaseMessagingService
扩展了多个服务类.因此,在一个类别中收到的消息具有较高的优先级,而在另一个类别中则没有.
Problem
You are facing this issue because there is multiple service class that extends from FirebaseMessagingService
. Because of this, messages are received in one class with high priority and not the other.
将以下内容添加到您的 AndroidManifest.xml
文件
Add the following to your AndroidManifest.xml
file
<service android:name="io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService">
<intent-filter android:priority="100">
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
它如何工作?
在清单文件中为 FlutterFirebaseMessagingService
设置的优先级为零(默认),但在清单文件中为 HyperTrackMessagingService
声明的优先级为5(现在为4.8.0版)).上面的解决方案仅覆盖优先级,并允许传入消息进入 FlutterFirebaseMessagingService
而不是 HyperTrackMessagingService
.
How it works?
The priority set for FlutterFirebaseMessagingService
in its manifest file is zero (default) but HyperTrackMessagingService
in its manifest file is declared with a priority of 5 (version 4.8.0 now). The above solution simply overrides the priority and lets incoming messages come to FlutterFirebaseMessagingService
instead of HyperTrackMessagingService
.
尽管HyperTrack可以正常工作,但是HyperTrack使用FCM进行设备-服务器通信以进行优化,而没有FCM则无法运行.但是,您可能不会注意到这一点.
Although HyperTrack will work fine, HyperTrack uses FCM for device-server communication for optimization which won't function without FCM. However, you might not notice this.
使用反射将 HyperTrackMessagingService
中的传入消息转发到插件 hypertrack_plugin
中的 FlutterFirebaseMessagingService
中.
Forward incoming message in HyperTrackMessagingService
to FlutterFirebaseMessagingService
in the plugin hypertrack_plugin
using reflection.
- 您将需要下载 hypertrack_plugin 源代码并将其用作本地依赖项.如何?
- 在库
sdk-flutter/android/src/main/kotlin/com/hypertrack/sdk/flutter/MyFirebaseMessagingService.java
中创建一个新类
- You will need to download hypertrack_plugin source code and use it as a local dependency. How?
- Create a new class inside the library
sdk-flutter/android/src/main/kotlin/com/hypertrack/sdk/flutter/MyFirebaseMessagingService.java
package com.hypertrack.sdk.flutter;
import android.annotation.SuppressLint;
import android.util.Log;
import com.google.firebase.messaging.RemoteMessage;
import com.hypertrack.sdk.HyperTrackMessagingService;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressLint("LongLogTag")
public class MyFirebaseMessagingService extends HyperTrackMessagingService {
private static final String TAG = "MyFirebaseMessagingService";
private Class<?> serviceClass;
private Object serviceObject;
public MyFirebaseMessagingService() {
try {
serviceClass = Class.forName("io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService");
serviceObject = serviceClass.newInstance();
injectContext();
Log.d(TAG, "io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService is found");
} catch (Throwable t) {
Log.w(TAG, "Can't find the class io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService", t);
}
}
@Override
public void onNewToken(final String s) {
super.onNewToken(s);
injectToken(s);
}
@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
injectMessage(remoteMessage);
}
public void injectToken(String newToken) {
if (serviceClass != null) {
try {
Method sendTokenRefresh = serviceClass.getMethod("onNewToken", String.class);
sendTokenRefresh.invoke(serviceObject, newToken);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.w(TAG, "Can't inject token due to error ", e);
}
}
}
public void injectMessage(RemoteMessage remoteMessage) {
if (serviceClass != null) {
try {
Method sendTokenRefresh = serviceClass.getMethod("onMessageReceived", RemoteMessage.class);
sendTokenRefresh.invoke(serviceObject, remoteMessage);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.w(TAG, "Can't inject message due to error ", e);
}
}
}
private void injectContext() {
if (serviceObject != null) {
if (setField(serviceObject, "mBase", this)) {
Log.d(TAG, "context is set to io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService");
}
}
}
private boolean setField(Object targetObject, String fieldName, Object fieldValue) {
Field field;
try {
field = targetObject.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
field = null;
}
Class<?> superClass = targetObject.getClass().getSuperclass();
while (field == null && superClass != null) {
try {
field = superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
superClass = superClass.getSuperclass();
}
}
if (field == null) {
return false;
}
field.setAccessible(true);
try {
field.set(targetObject, fieldValue);
return true;
} catch (IllegalAccessException e) {
return false;
}
}
}
- 编辑清单文件
sdk-flutter/android/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hypertrack.sdk.flutter">
<application>
<service
android:name=".MyFirebaseMessagingService"
android:exported="false" >
<intent-filter android:priority="100" >
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
它是如何工作的?
从 HyperTrackMessagingService
扩展的 MyFirebaseMessagingService
在 AndroidManifest.xml
文件中声明为具有更高的优先级(肯定高于 HyperTrackMessagingService 代码>).这将使消息直接进入新类.这也将消除方法1中的限制.现在,我们也使用反射将消息转发到
FlutterFirebaseMessagingService
.
How it works?
MyFirebaseMessagingService
extended from HyperTrackMessagingService
, is declared in the AndroidManifest.xml
file with higher priority (definitely higher than HyperTrackMessagingService
). This will allow messages directly to come to the new class. This will also remove the limitation in method 1. Now we forward the message also to FlutterFirebaseMessagingService
using reflection.
没有限制,但是在更新主机库时,您需要手动更新 hypertrack_plugin
.最好在插件本身中拥有此更新,而此更新目前不存在(11月13日)
No limitation, but you need to manually update the hypertrack_plugin
when the host library is updated. It's good to have this update in the plugin itself which is not present now (Nov 13)
现在,我们将不触摸库中的任何代码,而是编写我们自己的代码.我们将以安全的方式提出解决方案.您不必添加 hypertrack_plugin
作为本地依赖项.
Now we will not touch any code in the library but write our own code. We will propose a solution in a safe way. You don't have to add hypertrack_plugin
as local dependencies.
- 创建类
< project_root>/android/app/src/main/< your_package_name>/MyFirebaseMessagingService.java
package com.example.myapp;
import android.annotation.SuppressLint;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressLint("LongLogTag")
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMessagingService";
// put all the firebase messaging service classes used in your project here
private String[] fcmClasses = new String[]{
"io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService",
"com.hypertrack.sdk.HyperTrackMessagingService"};
@Override
public void onNewToken(@NotNull String token) {
Log.d(TAG, "onNewToken()");
super.onNewToken(token);
injectToken(token);
}
@Override
public void onMessageReceived(@NotNull RemoteMessage remoteMessage) {
Log.d(TAG, "onMessageReceived()");
super.onMessageReceived(remoteMessage);
injectMessage(remoteMessage);
}
public void injectToken(String newToken) {
Log.d(TAG, "injectToken()");
for (String fcmClass : fcmClasses) {
try {
Class<?> serviceClass = Class.forName(fcmClass);
Object serviceObject = serviceClass.newInstance();
injectContext(serviceClass, serviceObject);
Method sendTokenRefresh = serviceClass.getMethod("onNewToken", String.class);
sendTokenRefresh.invoke(serviceObject, newToken);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClassNotFoundException | InstantiationException e) {
Log.w(TAG, "Can't inject token due to error ", e);
}
}
}
public void injectMessage(RemoteMessage remoteMessage) {
Log.d(TAG, "injectMessage()");
for (String fcmClass : fcmClasses) {
try {
Class<?> serviceClass = Class.forName(fcmClass);
Object serviceObject = serviceClass.newInstance();
injectContext(serviceClass, serviceObject);
Method sendTokenRefresh = serviceClass.getMethod("onMessageReceived", RemoteMessage.class);
sendTokenRefresh.invoke(serviceObject, remoteMessage);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClassNotFoundException | InstantiationException e) {
Log.w(TAG, "Can't inject token due to error ", e);
}
}
}
private void injectContext(Class<?> serviceClass, Object serviceObject) {
Log.d(TAG, "injectContext()");
if (serviceClass != null) {
if (setField(serviceObject, "mBase", this)) {
Log.d(TAG, "context is set to " + serviceClass.getName());
}
}
}
private boolean setField(Object targetObject, String fieldName, Object fieldValue) {
Log.d(TAG, "setField()");
Field field;
try {
field = targetObject.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
field = null;
}
Class<?> superClass = targetObject.getClass().getSuperclass();
while (field == null && superClass != null) {
try {
field = superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
superClass = superClass.getSuperclass();
}
}
if (field == null) {
return false;
}
field.setAccessible(true);
try {
field.set(targetObject, fieldValue);
return true;
} catch (IllegalAccessException e) {
return false;
}
}
}
- 在
< project_root>/couriers/android/app/src/main/AndroidManifest.xml
中声明
重要:设置优先级高于5(在HyperTrack SDK中声明的优先级)
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter android:priority="100">
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
它如何工作?
我们已经明确创建了 MyFirebaseMessagingService
,并从 FirebaseMessagingService
进行了扩展.我们还将优先级设置为最高100,以确保仅在此处接收传入消息,而在任何其他Firebase消息传递服务(例如HyperTrack)中均不会接收到.现在,我们可以通过反射灵活地将邮件转发到任何需要的地方.
How does it work?
We have created MyFirebaseMessagingService
explicitly and extended from FirebaseMessagingService
. We also have set a priority as high as 100 to make sure we are receiving incoming messages only here and not in any other firebase messaging service such as HyperTrack. Now we have the flexibility to forward this message wherever we need, using reflection.
无
这篇关于Hypertrack阻止Flutter中的FCM通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!