Closed anas-iqbal closed 3 years ago
Hello @anas-iqbal
When the application is in a background or killed state, the onMessageReceivedStream handler will not be called when receiving data messages. Instead, you need to setup a background callback handler via the registerBackgroundMessageHandler method.
To setup a background handler, call the registerBackgroundMessageHandler outside of your application logic
as early as possible:
Step 1
Add an Application.java class to your app in the same directory as your MainActivity.java. This is typically found in ./android/app/src/main/java/\
package com.huawei.hms.flutter.push_example;
import com.huawei.hms.flutter.push.PushPlugin;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class Application extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {
@Override
public void onCreate() {
super.onCreate();
PushPlugin.setPluginRegistrant(this);
}
@Override
public void registerWith(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}
Step 2 In Application.java, make sure to change package com.huawei.hms.flutter.push_example; to your package's identifier. Your package's identifier should be something like com.domain.application_name
package com.domain.application_name;
Step 3 Set name property of application in AndroidManifest.xml. This is typically found in ./android/app/src/main/
<application
android:name=".Application"
android:icon="@mipmap/ic_launcher"
android:label="HMS Push Demo" ... >
....
</application>
Step 4 Define a top-level or static function to handle background data messages
//main.dart
static void backgroundMessageCallback(RemoteMessage remoteMessage) async {
String data = remoteMessage.data;
Push.localNotification({
HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received',
HMSLocalNotificationAttr.MESSAGE: data
});
}
Step 5 Set backgroundMessageCallback handler when calling registerBackgroundMessageHandler
//main.dart
...
@override
void initState() {
super.initState();
...
bool backgroundMessageHandler =
await Push.registerBackgroundMessageHandler(backgroundMessageCallback);
print("backgroundMessageHandler registered: $backgroundMessageHandler");
...
}
...
static void backgroundMessageCallback(RemoteMessage remoteMessage) async {
String data = remoteMessage.data;
Push.localNotification({
HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received',
HMSLocalNotificationAttr.MESSAGE: data
});
}
You can find a proper working demo app in the example folder 👍👍
Thank you for responding, if you refer to my code again u will see that I have already implemented registerBackgroundMessageHandler and it does gets called but it gives error on the following line inside backgroundMessageCallback method u can see below
static void backgroundMessageCallback(RemoteMessage remoteMessage) async {
String data = remoteMessage.data;
Push.localNotification({
HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received',
HMSLocalNotificationAttr.MESSAGE: 'Hello My Name'
}); // THIS LINE GIVES THE ERROR
print("onRemoteMessageReceived" + " Data: " + data);
}
Additionally your sample code is written on java, since I am using kotlin so your sample code isn't helping me much and even gives me the following error Type mismatch: inferred type is PluginRegistry but FlutterEngine was expected when I convert this method below
override fun registerWith(registry: PluginRegistry) {
GeneratedPluginRegistrant.registerWith(registry) // red line on registry and gives the above mismatch error
// That is why I am using the below line instead
registry?.registrarFor("com.huawei.hms.flutter.push.PushPlugin");
}
As per your answer I also moved the registerBackgroundMessageHandler before any logic right after init but didn't help either. Please advise.
Thanks
Also sharing the result of my flutter doctor if it helps.
[✓] Flutter (Channel stable, 1.20.3, on Mac OS X 10.15.5 19F101, locale en-PK)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3) [✓] Xcode - develop for iOS and macOS (Xcode 11.3.1) [!] Android Studio (version 4.1) ✗ Flutter plugin not installed; this adds Flutter specific functionality. ✗ Dart plugin not installed; this adds Dart specific functionality. [✓] VS Code (version 1.52.0)
@anas-iqbal thank you for your interest 😊
You should separate Activity and Application files like that;
//MainActivity.java
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
//MainApplication.java
import com.huawei.hms.flutter.push.PushPlugin;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class Application extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {
@Override
public void onCreate() {
super.onCreate();
PushPlugin.setPluginRegistrant(this); // <--- Add this line
}
@Override
public void registerWith(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}
and you should remove flutterEmbedding from AndroidManifest.xml file.
<meta-data
android:name="flutterEmbedding"
android:value="2" />
The Android embedding v2 includes support for standard Android life-cycle events and the separation of Flutter execution from the Android UI, for using that backgroundMessageHandler
we should remove that embedding 👍
@aktug thanks for getting back to me, I tried removing the below lines from manifest
<meta-data
android:name="flutterEmbedding"
android:value="2" />
but after that my project stopped building as my project is build on Android embedding v2 (as it is recommended by Flutter) and most of the plugins I am using requires Android embedding v2 I am getting below errors,
The plugin `plugin name` requires your app to be migrated to the Android embedding v2. Follow the steps on https://flutter.dev/go/android-project-migration
MainActivity.kt: (108, 48): Type mismatch: inferred type is FlutterEngine but PluginRegistry! was expected
I think downgrading my project to v1 won't be an option so is there any work around we can do to get it running on flutterEmbedding v2 projects?
Thank you
@aktug Some packages in my existing project are dependent on v2 embedding. Removing this line causes those plugins to crash. Additionally, I believe Flutter devs are encouraging to use v2 embedding moving forward. Any possibility we can get a working sample with latest Flutter version and Kotlin with embedding v2 enabled?
Hello @obaid-saleem and @anas-iqbal ,
When we're developing this background feature, there was not any other solution for implementing this feature without downgrading to flutterEmbedding v1, did not figure it out without it.
For now, if anyone wants to use the backgroundMessageHandler feature, should remove that metadata or downgrade to v1. We're chasing the Flutter change history, if a more reliable way to implement this feature with v2, we'll update our plugin and we're open to new ideas as always 👍
Thank you for your interest 👍
Hello @aktug
Finally got it working with flutterEmbedding v2, after registering the plugin manually in my application class. Below is my updated application class
class MainApplication : FlutterApplication(), PluginRegistry.PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
PushPlugin.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry?) {
if (!registry!!.hasPlugin("com.huawei.hms.flutter.push.PushPlugin")) {
PushPlugin.registerWith(registry?.registrarFor("com.huawei.hms.flutter.push.PushPlugin"))
}
}
}
I think we have manually register the v1 plugins in v2 projects in order to use them.
Hello @aktug
I just ran into another problem, can you please have a look? I am getting data on my background message handler method, but then user clicks on notification and my onNotificationOpenedApp is called I am not getting any data. as you can see in the images below
notification on background method (it's showing the data)
Same notification on notification tap method (data is null)
Case 1: Notification Message This type of message does not trigger onMessageReceived event. You can access datas and infos from onNotificationOpenedApp
Case 2: Data Message This type of message triggers onMessageReceived event. In the demo project, if any "data message" received, the Push.localNotification method calling with these received data message's title and message infos. As you can see, there is no field for data in that method so we can't set any data to localnotifications. We noted that the feature will be implemented in the next version.
Thank you so much for your collaborations 🤩
I know its an old and closed issue, but just for an update so if may help anyone, I ended up using flutter local notification plugin along with this plugin for handling data payload. :)
the backgroundMessageCallback MUST BE a top-level or static function
Hi everyone, if you are searching information about backgroundMessageHandler using flutter v2 pls follow this link https://developer.huawei.com/consumer/en/doc/HMS-Plugin-Guides/receiving-data-messages-at-killed-state-0000001058199547?ha_source=hms1. And create the backgrounMessageCallback like this
@pragma('vm:entry-point') void onMessageReceived(RemoteMessage remoteMessage) { String data = remoteMessage.getData ?? '';
if (data.isNotEmpty) {
try {
final hNotification = Model.fromJson(data);
Push.localNotification({
HMSLocalNotificationAttr.TITLE: hNotification.title,
HMSLocalNotificationAttr.MESSAGE: hNotification.message,
HMSLocalNotificationAttr.BIG_PICTURE_URL: hNotification.image,
HMSLocalNotificationAttr.LARGE_ICON: hNotification.image,
HMSLocalNotificationAttr.SMALL_ICON: '@drawable/ic_huawei_notification',
});
} catch (error) {
debugPrint('error local notification: ${error.toString()}');
}
} }
@pragma('vm:entry-point') is the most important code to wake up in background like FirebaseNotifications this work for me in app gallery deployed. And is not in official documentation
This code work actually in 2024 using flutter huawei_push: ^6.12.0+302. I hope help to anyone :)
Hi, I have implemented HMS push kit and everything is working fine except background message handler, Push.onMessageReceivedStream is working fine but when I send notification when app is on background I get error in backgroundMessageCallback, I get the following error
Unhandled Exception: MissingPluginException(No implementation found for method localNotification on channel com.huawei.flutter.push/method)
I am posting my code below, please let me know if any additional code required, thanks :)
version on pubsec : huawei_push: ^5.0.2+301
My Application class
My HMS helper function ( which I call on main.dart)
manifiest
build grade