是否可以在系统托盘中接收仅数据通知?
Is it possible to recieve data only notifications in the system tray?
我从 CloudFunction
发送了一个包含以下负载的通知
const payload: admin.messaging.MessagingPayload = {
// notification: {
// title: `${translator['messageTitle' as keyof typeof translator]} ${group.displayName}`,
// body: `${sender.displayName} ${translator[type as keyof typeof translator]}`,
// clickAction: 'FLUTTER_NOTIFICATION_CLICK',
// },
data: {
title: `${translator['messageTitle' as keyof typeof translator]} ${group.displayName}`,
body: `${sender.displayName} ${translator[type as keyof typeof translator]}`,
clickAction: 'FLUTTER_NOTIFICATION_CLICK',
senderId: sender.id,
senderDisplayName: sender.displayName,
groupId: group.id,
type: 'groupMessage',
messageType: type,
sentAt: new Date().toISOString(),
}
}
为了让 OnBackgroundMessage 正常工作,我需要从我的负载中删除通知部分。但这也意味着它们不会再出现在我的系统托盘中。我怎样才能在我的系统托盘中显示它们?是否涉及制作通知渠道?
我加了Application.kt
package HERE_I_HAVE_MY_PACKAGE_NAME
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
public class Application: FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry) {
FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
}
}
和FirebaseCloudMessagingPluginRegistrant.kt
package HERE_I_HAVE_MY_PACKAGE_NAME
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
class FirebaseCloudMessagingPluginRegistrant {
companion object {
fun registerWith(registry: PluginRegistry) {
if (alreadyRegisteredWith(registry)) {
return;
}
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"))
}
fun alreadyRegisteredWith(registry: PluginRegistry): Boolean {
val key = FirebaseCloudMessagingPluginRegistrant::class.java.name
if (registry.hasPlugin(key)) {
return true
}
registry.registrarFor(key)
return false
}
}
}
这是我的 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company_name.app_name">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name=".Application"
android:label="App Name"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
</application>
</manifest>
我将 flutter_local_notifications
插件与 FCM 一起使用,一旦您拥有后台消息处理程序,处理数据并调用显示通知的函数,插件将为您创建通知。
一个例子:
这应该在某种帮助程序中 class:
static Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
if (message.containsKey('data')) {
final body = message['data']['message'];
final title = message['data']['title'];
final notifications = FlutterLocalNotificationsPlugin();
showOngoingNotification(notifications,title, body);
}
}
static NotificationDetails get _dets {
final androidChannelSpecifics = AndroidNotificationDetails(
'channel id',
'channel name',
'channel description',
importance: Importance.Max,
priority: Priority.High,
ongoing: false,
autoCancel: true,
);
final iOSChannelSpecifics = IOSNotificationDetails();
return NotificationDetails(androidChannelSpecifics, iOSChannelSpecifics);
}
static Future showOngoingNotification(FlutterLocalNotificationsPluginnotifications,String title, String body) async
var id = 0;
var payload = 'somepayload';
NotificationDetails dets = _dets;
notifications.show(id, title, body, dets, payload: payload)
}
这是在main.dart:
final notifications = FlutterLocalNotificationsPlugin();
void InitializeLocalNotifs(){
final settingsAndroid = AndroidInitializationSettings('app_icon'); //make sure this is the same name as your icon
final settingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: (id, title, body, payload) =>
onSelectNotification(payload)); //if you want to get permissions at a different time set everything to false and ask for them later
notifications.initialize(
InitializationSettings(settingsAndroid, settingsIOS),
onSelectNotification: onSelectNotification);
}
Future onSelectNotification(String payload) async {
//do whatever with payload, I usually send the page to push in the payload and push it like this
// await Navigator.pushNamed(context, payload);
}
@override
void initState() {
InitializeLocalNotifs();
InitializeFCM();
super.initState();
}
我最终发送了 2 条有效的通知。 1 个带有通知和数据对象,另一个仅带有数据对象。在我的前端,我检查它是否是仅数据通知。
我从 CloudFunction
发送了一个包含以下负载的通知 const payload: admin.messaging.MessagingPayload = {
// notification: {
// title: `${translator['messageTitle' as keyof typeof translator]} ${group.displayName}`,
// body: `${sender.displayName} ${translator[type as keyof typeof translator]}`,
// clickAction: 'FLUTTER_NOTIFICATION_CLICK',
// },
data: {
title: `${translator['messageTitle' as keyof typeof translator]} ${group.displayName}`,
body: `${sender.displayName} ${translator[type as keyof typeof translator]}`,
clickAction: 'FLUTTER_NOTIFICATION_CLICK',
senderId: sender.id,
senderDisplayName: sender.displayName,
groupId: group.id,
type: 'groupMessage',
messageType: type,
sentAt: new Date().toISOString(),
}
}
为了让 OnBackgroundMessage 正常工作,我需要从我的负载中删除通知部分。但这也意味着它们不会再出现在我的系统托盘中。我怎样才能在我的系统托盘中显示它们?是否涉及制作通知渠道?
我加了Application.kt
package HERE_I_HAVE_MY_PACKAGE_NAME
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
public class Application: FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry) {
FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
}
}
和FirebaseCloudMessagingPluginRegistrant.kt
package HERE_I_HAVE_MY_PACKAGE_NAME
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
class FirebaseCloudMessagingPluginRegistrant {
companion object {
fun registerWith(registry: PluginRegistry) {
if (alreadyRegisteredWith(registry)) {
return;
}
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"))
}
fun alreadyRegisteredWith(registry: PluginRegistry): Boolean {
val key = FirebaseCloudMessagingPluginRegistrant::class.java.name
if (registry.hasPlugin(key)) {
return true
}
registry.registrarFor(key)
return false
}
}
}
这是我的 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company_name.app_name">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name=".Application"
android:label="App Name"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
</application>
</manifest>
我将 flutter_local_notifications
插件与 FCM 一起使用,一旦您拥有后台消息处理程序,处理数据并调用显示通知的函数,插件将为您创建通知。
一个例子:
这应该在某种帮助程序中 class:
static Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
if (message.containsKey('data')) {
final body = message['data']['message'];
final title = message['data']['title'];
final notifications = FlutterLocalNotificationsPlugin();
showOngoingNotification(notifications,title, body);
}
}
static NotificationDetails get _dets {
final androidChannelSpecifics = AndroidNotificationDetails(
'channel id',
'channel name',
'channel description',
importance: Importance.Max,
priority: Priority.High,
ongoing: false,
autoCancel: true,
);
final iOSChannelSpecifics = IOSNotificationDetails();
return NotificationDetails(androidChannelSpecifics, iOSChannelSpecifics);
}
static Future showOngoingNotification(FlutterLocalNotificationsPluginnotifications,String title, String body) async
var id = 0;
var payload = 'somepayload';
NotificationDetails dets = _dets;
notifications.show(id, title, body, dets, payload: payload)
}
这是在main.dart:
final notifications = FlutterLocalNotificationsPlugin();
void InitializeLocalNotifs(){
final settingsAndroid = AndroidInitializationSettings('app_icon'); //make sure this is the same name as your icon
final settingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: (id, title, body, payload) =>
onSelectNotification(payload)); //if you want to get permissions at a different time set everything to false and ask for them later
notifications.initialize(
InitializationSettings(settingsAndroid, settingsIOS),
onSelectNotification: onSelectNotification);
}
Future onSelectNotification(String payload) async {
//do whatever with payload, I usually send the page to push in the payload and push it like this
// await Navigator.pushNamed(context, payload);
}
@override
void initState() {
InitializeLocalNotifs();
InitializeFCM();
super.initState();
}
我最终发送了 2 条有效的通知。 1 个带有通知和数据对象,另一个仅带有数据对象。在我的前端,我检查它是否是仅数据通知。