【发布时间】:2019-05-03 11:16:09
【问题描述】:
我已经构建了一个带有 Flutter 的应用程序,它的工作原理就像一个提醒。
即使应用程序关闭,如何向用户显示通知?
【问题讨论】:
标签: push-notification flutter apple-push-notifications android-notifications mobile-application
我已经构建了一个带有 Flutter 的应用程序,它的工作原理就像一个提醒。
即使应用程序关闭,如何向用户显示通知?
【问题讨论】:
标签: push-notification flutter apple-push-notifications android-notifications mobile-application
对于提醒,我会推荐Flutter Local Notifications Plugin。它有一个强大的调度API。来自本地通知的文档:
安排通知应出现的时间 - 定期显示 通知(基于间隔) - 安排要显示的通知 每天在指定时间 - 安排每周显示通知 在指定的日期和时间 - 能够在应用处于前台、后台或终止
时处理用户点击通知的情况
对于推送通知,您可以使用Firebase Cloud Messaging 或one signal 插件,也可以通过platform-channels 原生实现
编辑:即使应用程序终止,您也可以根据特定条件触发通知。这可以通过在后台运行 dart 代码来实现。引用官方常见问题:
我可以在 Flutter 应用的后台运行 Dart 代码吗?是的你可以 在 iOS 和 Android 的后台进程中运行 Dart 代码。为了 更多信息,请参阅 Medium 文章Executing Dart in the Background with Flutter Plugins and Geofencing.
【讨论】:
我已经找到了解决这个问题的方法。我们只需要在Application类中注册Local Notification Plugin即可。
首先创建一个类 FlutterLocalNotificationPluginRegistrant,我在 Kotlin 中创建了这个。
class FlutterLocalNotificationPluginRegistrant {
companion object {
fun registerWith(registry: PluginRegistry) {
if (alreadyRegisteredWith(registry)) {
Log.d("Local Plugin", "Already Registered");
return
}
FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"))
Log.d("Local Plugin", "Registered");
}
private fun alreadyRegisteredWith(registry: PluginRegistry): Boolean {
val key = FlutterLocalNotificationPluginRegistrant::class.java.canonicalName
if (registry.hasPlugin(key)) {
return true
}
registry.registrarFor(key)
return false
}
}}
现在创建一个扩展 FlutterApplication 的 Application 类并实现 PluginRegistry.PluginRegistrantCallback。
class Application : FlutterApplication(), PluginRegistry.PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
}
override fun registerWith(registry: PluginRegistry?) {
if (registry != null) {
FlutterLocalNotificationPluginRegistrant.registerWith(registry)
}
}}
并在AndroidManifest.xml中注册Application类
<application
android:name="com.packagename.Application"/>
全部完成。现在编写一个函数来显示通知并从 Firebase 消息传递的后台处理程序方法调用它。
Future _showNotificationWithDefaultSound(String title, String message) async {
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'channel_id', 'channel_name', 'channel_description',
importance: Importance.Max, priority: Priority.High);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'$title',
'$message',
platformChannelSpecifics,
payload: 'Default_Sound',
);
}
然后这样称呼它。
Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async {
if (message['data'] != null) {
final data = message['data'];
final title = data['title'];
final body = data['message'];
await _showNotificationWithDefaultSound(title, message);
}
return Future<void>.value();
}
【讨论】:
我也遇到过这个问题,所以这些是我的学习
在我的情况下:我能够在 App-Resume 或 App-background 状态下收到通知,但在 App-Close 状态下,我没有收到通知。
在这种情况下,我们的通知正文是:
{notification: {body: null, title: null}, data: {body: hello, title: world}}
为了在 App-Closed 状态下接收通知,我们将通知更改为
{notification: {body: abc, title: abc}, data: {url: string, body: string, title: string}}
【讨论】:
您可以在 Flutter 中使用计划通知。
var scheduledNotificationDateTime =
new DateTime.now().add(new Duration(seconds: 5));
var androidPlatformChannelSpecifics =
new AndroidNotificationDetails('your other channel id',
'your other channel name', 'your other channel description');
var iOSPlatformChannelSpecifics =
new IOSNotificationDetails();
NotificationDetails platformChannelSpecifics = new
NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.schedule(
0,
'scheduled title',
'scheduled body',
scheduledNotificationDateTime,
platformChannelSpecifics);
【讨论】:
对于那些使用 2.2 左右最新版本的用户,只需调用 firebaseMessageInstance
FirebaseMessaging.instance.getInitialMessage().then((message) =>
message.messageId.isNotEmpty
? print('we can now navigate to specific screen')
: print('there is no new notification so default screen will be shown when application start from terminated state'));
别忘了打电话
Navigator.push(
context, MaterialPageRoute(builder: (context) => YourScreenName()));
当 message.messageId.isNotEmpty
如果您喜欢这种方法,请点赞,感谢您度过愉快的编码日
【讨论】: