本指南讨论如何实现本地和推送通知。
Solar2D 支持两种类型的通知:本地和推送。两种通知类型的目的都是为了在应用程序不在前台运行时通知用户某些事情——例如,消息或即将到来的约会。本地通知和推送通知之间的本质区别很简单:
本地通知由应用程序在本地安排,并由同一设备传送。
推送通知由远程服务器(其提供商)发送,该服务器将这些通知发送到安装了该应用程序的设备。
通知仅在 iOS 和 Android 上受支持,macOS 桌面、Windows 桌面、Apple TV 或 Android TV 上不受支持。
要使用推送通知,请记住以下几点:
应用程序如何响应通知取决于其状态:
未运行 - 应用程序已按设计退出、用户决定、重新启动等。在这种状态下,如果用户与通知交互,操作系统将启动应用程序。有关通知事件的信息将使用“启动参数”传递给应用程序。应用程序应监视这些参数并做出相应的反应,例如,显示闹钟的“稍后提醒”按钮,或者如果它有 URL,则打开 native.newWebView()。但是请注意,如果用户直接点击其图标启动应用程序,则不会显示通知。
后台运行 - 应用程序正在运行,但它不是活动的应用程序。在这种状态下,如果用户通过在显示通知时在解锁屏幕上滑动或在通知中心点击通知来与通知交互,操作系统会将应用程序置于前台并使其处于活动状态。此时,应用程序将接收通知事件,但不会接收启动参数。
前台运行 - 应用程序处于活动状态,并且用户当前正在与其交互。在这种状态下,应用程序将接收通知事件。
要使用 通知 插件,请在 `build.settings` 的 `plugins` 表中添加一个条目。添加后,构建服务器将在构建阶段集成该插件。
settings = { plugins = { ["plugin.notifications.v2"] = { publisherId = "com.coronalabs" }, }, }
在此 `build.settings` 文件中,还要包含 `minSdkVersion` 16 或更高版本。有关设置最低 SDK 版本的更多信息,请参阅此处。
settings = { android = { minSdkVersion = "16", }, }
然后,在使用通知函数的代码模块中,只需按如下方式 `require()` 该库:
local notifications = require( "plugin.notifications.v2" )
对于 Android,所有新应用或首次使用推送通知更新的现有应用都必须使用 Firebase 云消息传递 (FCM),当前的 通知 插件(上方)支持该功能。如果您有一个已为 Google 云消息传递 (GCM) 配置的旧版应用,它将继续无限期地工作,但您应继续使用 旧版 插件,而不是当前的通知插件。
对于 iOS,您可以使用 Apple 推送通知服务 (APNS) 或 Firebase 云消息传递 (FCM) 进行推送通知(请参阅下文)。
推送通知的大部分 iOS 配置都在 Apple Developer 门户网站中完成。此外,您必须在 `config.lua` 的
application = { notification = { iphone = { types = { "badge", "sound", "alert" }, }, }, }
如果您想使用 Google Firebase 云消息传递 (FCM) 进行推送通知,请按照以下附加步骤操作:
将 Firebase 控制台中提供的 `GoogleService-Info.plist` 复制到与 `main.lua` 并列的项目根目录中。
将以下条目添加到 `build.settings` 的
settings = { iphone = { plist = { UIBackgroundModes = { "remote-notification" }, FirebaseAppDelegateProxyEnabled = false, }, }, }
Android 也需要对推送通知进行一些额外的配置:
将 Firebase 控制台中提供的 `google-services.json` 复制到与 `main.lua` 并列的项目根目录中。
在 `build.settings` 的 `android` 表中添加一个额外的 `useGoogleServicesJson` 条目。添加后,构建服务器将从 JSON 文件中读取设置,并在构建阶段将它们集成到您的应用程序中。
settings = { android = { useGoogleServicesJson = true, }, }
您可以通过将以下文件添加到项目目录的根目录(就像自定义应用程序图标一样)来设置项目中的自定义通知图标。有关更多详细信息,请参阅 Google 的官方文档。
文件 | 大小 (宽×高) |
---|---|
IconNotificationDefault-ldpi.png |
18 × 18 |
IconNotificationDefault-mdpi.png |
24 × 24 |
IconNotificationDefault-hdpi.png |
36 × 36 |
IconNotificationDefault-xhdpi.png |
48 × 48 |
IconNotificationDefault-xxhdpi.png |
72 × 72 |
IconNotificationDefault-xxxhdpi.png |
96 × 96 |
要安排本地通知,请使用 notifications.scheduleNotification() 函数,并使用以下两种格式之一指定未来事件的时间:
从调用时间算起应传送通知的秒数。
以协调世界时 (UTC) 指定的时间。这应该是 `os.date("!*t")` 返回的时间表。请注意,一个常见的错误是忘记感叹号并传递 `"*t"` 而不是 `"!*t"`——这将以本地时间(您的时区)而不是 UTC 返回时间结构。
您还应传递一个包含以下任何参数的 `options` 表:
`alert`(字符串)——要向用户显示的通知消息。如果应用程序当前未运行,系统警报将显示此消息。
`badge`(数字)——此选项仅在 iOS 上受支持,它指示在计划的通知触发时应用程序图标上显示的徽章编号。这将替换上次应用的徽章编号。设置为 `0` 可省略徽章编号。
`sound`(字符串)——system.ResourceDirectory 中要在计划的通知触发时播放的声音文件的名称。仅当应用当前不在前台运行时才会播放此声音。在 iOS 上,可以播放的声音种类有限制(有关更多详细信息,请参阅 Apple 的文档)。
`custom`(表)——将随通知事件一起传送的表。这允许您传递带有通知的自定义信息。
要在本地通知触发之前取消它,请使用 notifications.cancelNotification() 函数并传递 notifications.scheduleNotification() 返回的 ID。
根据 Solar2D 事件/侦听器模型,如果您的应用程序在前台或后台运行并且收到通知,您将收到一个 notification 事件。您有责任初始化系统并设置侦听器函数来处理这些事件。请查看以下框架,然后阅读下面的详细小节。
local function notificationListener( event ) if ( event.type == "remote" ) then -- Handle the push notification elseif ( event.type == "local" ) then -- Handle the local notification end end Runtime:addEventListener( "notification", notificationListener )
notification 事件返回一个信息表,您可以使用它来管理特定通知。此表包括以下内容:
当操作系统由于传入通知而从非活动(未运行)状态启动您的应用程序时,应用程序会将数据作为 `launchArgs` 的一部分接收,而不是触发通知事件。您可以使用 `notificationListener` 函数来处理启动参数。
local launchArgs = ... if ( launchArgs and launchArgs.notification ) then notificationListener( launchArgs.notification ) end
此 `launchArgs` 处理必须在 `main.lua` 中,因为它是接收数据的代码。
iOS 上的通知徽章很容易通过覆盖在应用程序图标上的小圆圈/数字来识别。如果通知传递了 `badge` 值,则等于该值的徽章将出现在应用程序图标上。
您有责任读取并根据其先前值设置徽章编号。这可以通过 native.getProperty() 和 native.setProperty() 函数来完成。几乎在所有情况下,当用户打开/处理通知时,您应该将徽章编号减 1,如下所示
-- Decrement the badge number by 1 local function notificationListener( event ) if ( event.type == "local" ) then -- Handle the local notification local badgeNum = native.getProperty( "applicationIconBadgeNumber" ) if ( badgeNum > 0 ) then badgeNum = badgeNum - 1 native.setProperty( "applicationIconBadgeNumber", badgeNum ) end elseif ( event.type == "remote" ) then -- Handle the push notification if ( event.badge and event.badge > 0 ) then native.setProperty( "applicationIconBadgeNumber", event.badge - 1 ) end end end
或者,您可以完全清除徽章
native.setProperty( "applicationIconBadgeNumber", 0 )
默认情况下,设备会在收到通知时播放声音。您可以在项目中指定自定义声音文件来代替默认声音。例如,如果您的应用程序包中包含文件 notification.wav
,您可以将字符串 "notification.wav"
指定为推送包的一部分(如果发送服务支持的话),操作系统将播放该自定义声音而不是默认声音。在这种情况下,事件侦听器中的 event.sound
条目将等于此字符串。
在 iOS 上,当您准备好请求用户允许推送通知的权限时,您应该调用 notifications.registerForPushNotifications()。这将显示一个弹出窗口,询问用户是否要启用推送通知。建议您仅在需要时才请求此权限,而不是在应用程序启动时。
如果您正在使用 Google Firebase 云消息传递 (FCM) 进行推送通知,则应向 notifications.registerForPushNotifications() 传递一个附加参数。此参数应该是一个包含 useFCM
键且值为 true
的 表
notifications.registerForPushNotifications( { useFCM=true } )
调用 notifications.registerForPushNotifications() 将触发向您的通知侦听器函数发送远程注册事件。为了适应这种情况,添加一个附加条件
local function notificationListener( event ) if ( event.type == "remote" ) then -- Handle the push notification elseif ( event.type == "remoteRegistration" ) then -- Code to register your device with the service elseif ( event.type == "local" ) then -- Handle the local notification end end