推送
Player Network SDK 的推送模块为游戏提供推送通知服务。推送功能分为本地通知和远程推送两种。本地通知功能使游戏在不运行的情况下也能向用户发送推送通知,如节日活动和周年纪念活动等。
Android 12 及以上系统,因 Android API 对 SCHEDULE_EXACT_ALARM
权限申请的收紧,Player Network SDK 使用了内部延时触发来实现推送。因此在关闭 app 后将无法触发延时代码。触发时间也因系统休眠策略会有误差。
同时推送多条消息、或当客户端因切换 网络等原因而导致网络波动时,部分消息可能存在延时收到的情况。
由于 Firebase Cloud Messaging 依赖 Google Mobile Services 来实现消息推送,华为设备因不会预装 Google Mobile Services 而无法正常收到推送消息。
前提条件
开始使用 本地通知 只需 接入 Player Network SDK。
远程推送通知 使用 Firebase 的推送功能来实现,使用远程推功能需要完成以下步骤:
1. 注册 Firebase 项目
在 Firebase Console 页面根据提示注册 Firebase 项目。
2. 添加应用
Firebase 支持 多商店渠道包,同一开发者账号下可以创建多个 app。只需要在同一个 Firebase 项目下填新的渠道包名和对应签名配置,并通过重复以下步骤完成额外游戏应用的配置。
-
在 Firebase Console 的 Project Overview 页面,添加对应平台的 Firebase 应用。
-
根据提示添加相应的资料。
-
添加 Android 应用。
- 填 写信息后,点击 REGISTER APP。
如果部分字段不确认,可以后续在设置中补充。 - 下载
google-services.json
文件备用,后续也可以在 Firebase Console 重新下载。 - 跳过其他步骤。
- 填 写信息后,点击 REGISTER APP。
-
添加 iOS 应用。
- 填写信息后,点击 REGISTER APP。
如果部分字段不确认,可以后续在设置中补充。 - 下载
google-services.json
文件备用,后续也可以在 Firebase Console 重新下载。 - 配置推送功能的 APN 证书。
- 填写信息后,点击 REGISTER APP。
3. 上传 iOS APNs 证书
-
在 Settings 页面,点击 CLOUD MESSAGING 并找到 iOS 项目。
-
分别添加 开发证书 和 正式证书。
详细信息,请参见 设置 Apple 平台客户端。
4. 项目配置
在 Project settings 中可以继续设置项目信息,下载 google-services.json
和 GoogleService-Info.plist
,或者配置好 Android 证书指纹。
步骤1:权限和工程配置
本地通知
在 Android 的 INTLConfig.ini 中添加以下配置。
[Android Local Notification]
ANDROID_LOCAL_NOTIFICATION_ENABLE = 1
远程推送
推送模块的 Firebase 远程推送配置。
Android
用户权限
由于 Firebase SDK 只兼容 minSdkVersion >= 19,所以在 Android 4.2 以下系统上运行可能会存在问题,需要游戏设置 minSdkVersion >= 19。
- Unity
- Unreal Engine
Firebase 需要访问网络的权限,请在 Assets/Plugins/Android/AndroidManifest.xml
中配置 Unity 权限。
Firebase 需要访问网络的权限,请到 Project Settings > Platforms > Android > Extra Permission 配置 Unreal Engine 权限。
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
工程配置
没有 google-services.json
文件会导致打包失败。
- Unity
- Unreal Engine
Gradle 打包方式支持从 google-services.json
文件直接读取内容,转化成对应的 app/build/generated/res/google-services/{build_type}/values/values.xml
配置文件。
有关在项目的 Assets/Plugins/Android/
目录下添加 google-services.json
文件的更多详情,请参见 The Google Services Gradle Plugin。
Gradle 打包方式支持从 google-services.json
文件直接读取内容,转化成对应的 app/build/generated/res/google-services/{build_type}/values/values.xml
配置文件。
有关在项目的 Plugins/INTLSDK/Source/INTLFirebase/Libs/Android
目录下添加 google-services.json
文件的更多详情,请参见 The Google Services Gradle Plugin。
[可选] 配置默认背景颜色
- Unity
- Unreal Engine
在配置通知时指定颜色,使用该颜色作为通知横幅的默认背景颜色。
可以在 Unity 的 Assets/Plugins/Android/
目录下的 Android 工程目录下资源文件中定义 color
。
例如:xxx/res/values/colors.xml。
<!-- 设置推送通知的颜色,当推送通知本身没有设置颜色时使用。
更多信息,请参见 README(https://goo.gl/6BKBk7)。 -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
在配置通知时指定颜色,使用该颜色作为通知横幅的默认背景颜色。
可以将颜色定义文件放在 INTLFirebase/Libs/Android/res/
目录下,然后在 INTLFirebase_APL.xml
中添加以下代码。颜色定义文件将被复制到 Android 资源目录并被用来设置推送背景颜色。
<resourceCopies>
<copyFile src="$S(PluginDir)/lib/Android/res/values.xml" dst="$S(BuildDir)/res/values/values.xml"/>
</resourceCopies>
<addElements tag="application">
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
</addElements>
[可选] 配置默认图标
- Unity
- Unreal Engine
在配置通知时指定图标,使用该图标作为通知的默认图标。
可以在 Unity 的 Assets/Plugins/Android/
目录下的 Android 工程目录下放置 drawable
文件。
例如:xxx/res/drawable
。
<!-- 设置自定义默认图标,当推送通知本身未设置图标时使用。
更多信息请参见 README(https://goo.gl/l4GJaQ)。 -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_ic_notification" />
在配置通知时指定图标,使用该图标作为通知的默认图标。
可以将图标文件放在 INTLFirebase/Libs/Android/drawable
目录下,然后在 INTLFirebase_APL.xml
中添加以下代码。图标将被复制到 Android 资源目录并被设置为推送图标。
<resourceCopies>
<copyDir src="$S(PluginDir)/drawable/" dst="$S(BuildDir)/res/drawable" />
</resourceCopies>
<addElements tag="application">
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_stat_ic_notification" />
</addElements>
Android 支持大小推送图标。
-
小图标显示在顶部状态栏以及通知横幅。
注意Android 5.0+ (API level 21+) 强制图标背景必须是白色和透明的。通知横幅的阴影可用强调色着色,但图标颜色不受强调色影响。
-
大图标的推荐大小为 256x256 像素,未设置时将使用小图标。大图标的显示位置取决于设备的 Android 版本:
- Android 4.0.3 - 6.0 (API level 15-23) 设备在通知文本的左侧显示。
- Android 7.0+ (API level 24+) 设备在通知文本的右侧显示。
推荐使用 Notification icon generator 工具自制合适解析度的推送图标。
像素密度 | 解析度 | 文件路径 |
---|---|---|
MDPI | 24 x 24 (drawable-mdpi) | Assets/Plugins/Android/res/drawable-mdpi/ |
HDPI | 36 x 36 (drawable-hdpi) | Assets/Plugins/Android/res/drawable-hdpi/ |
XHDPI | 48 x 48 (drawable-xhdpi) | Assets/Plugins/Android/res/drawable-xhdpi/ |
XXHDPI | 72 x 72 (drawable-xxhdpi) | Assets/Plugins/Android/res/drawable-xxhdpi/ |
XXXHDPI | 96 x 96 (drawable-xxxhdpi) | Assets/Plugins/Android/res/drawable-xxxhdpi/ |
XXXHDPI (大) | 256 x 256 (drawable-xxxhdpi) (大) | Assets/Plugins/Android/res/drawable-xxxhdpi/ |
iOS
工程配置
Firebase Plist
没有 GoogleService-info.plist
文件会导致启动崩溃。
替换配置文件 GoogleService-info.plist
至 Assets/Plugins/iOS/INTLSDK/INTLFirebase/ThirdSDK/
目录中。
- Unity
- Unreal Engine
Xcode 工程 push 开启
Unity 需要在 Xcode 工程中开启 Firebase push 功能。在导出 Xcode 工程前,需先完成 .projmods 文件的配置。
Player Network SDK 已经将以下配置写入 INTLFirebaseKit.projmods
文件中,业务只需确保信息正确无误。
{
"group": "INTL",
"libs": [],
"frameworks": [],
"files": [
"Plugins/iOS/INTLSDK/INTLFirebase/GoogleService-Info.plist"
],
"folders": [],
"excludes": [],
"headerpaths":[],
"build_settings": {},
"system_capabilities": {"com.apple.Push":"TRUE"},
"Info.plist":{},
}
有关 Xcode 工程导出的更多信息,请参见 Player Network SDK XUPorter 解决方案。
在完成导出后,在工程中 Capability > Background Modes > Push Notifications 下开启 Remote notifications。
iOS 推送适配
Unreal Engine 4.21 及以上版本,修改以下引擎源码:
-
IOSAppDelegate.h
class APPLICATIONCORE_API FIOSCoreDelegates
{
public:
// Broadcast when this application is opened from an external source
DECLARE_MULTICAST_DELEGATE_FourParams(FOnOpenURL, UIApplication*, NSURL*, NSString*, id);
DECLARE_MULTICAST_DELEGATE_TwoParams(FApplicationHandleEventsForBackgroundURLSessionDelegate, NSString*, NSDictionary*); // 添加的代码
static FOnOpenURL OnOpenURL;
static FApplicationHandleEventsForBackgroundURLSessionDelegate OnApplicationHandleEventsForBackgroundURLSessionDelegate; // 添加的代码
}; -
IOSAppDelegate.cpp
extern bool GShowSplashScreen;
FIOSCoreDelegates::FOnOpenURL FIOSCoreDelegates::OnOpenURL;
TArray<FIOSCoreDelegates::FFilterDelegateAndHandle> FIOSCoreDelegates::PushNotificationFilters;
FIOSCoreDelegates::FApplicationHandleEventsForBackgroundURLSessionDelegate FIOSCoreDelegates::OnApplicationHandleEventsForBackgroundURLSessionDelegate; // 添加的代码- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler
{
FString Id(identifier);
FCoreDelegates::ApplicationBackgroundSessionEventDelegate.Broadcast(Id);
completionHandler();
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:completionHandler, @"handler", nil]; // 添加的代码
FIOSCoreDelegates::OnApplicationHandleEventsForBackgroundURLSessionDelegate.Broadcast(identifier, dict); // 添加的代码
}
步骤2:注册回调
为推送模块添加以下回调。
- Unity
- Unreal Engine
API | Function |
---|---|
AddPushBaseResultObserver | 添加 Player Network SDK 推送模块的 BaseResult 回调 用于处理 RegisterPush 的接口回调 |
RemovePushBaseResultObserver | 移除 BaseResult 监听回调 |
AddPushResultObserver | 添加 Player Network SDK 推送模块的 PushResult 的回调 用于处理 AddLocalNotification 的接口回调 |
RemovePushResultObserver | 移除 PushResult 的回调 |
API | Function |
---|---|
SetPushBaseResultObserver | 设置 Player Network SDK 推送模块 BaseResult 的回调 |
GetPushBaseResultObserver | 获取 BaseResult 的回调 |
OnPushBase_Implementation | 实现 RegisterPush 接口 BaseResult 的回调 |
SetPushResultObserver | 设置 Player Network SDK 推送模块 PushResult 的回调 |
GetPushResultObserver | 获取 PushResult 的回调 |
OnPushResult_Implementation | 实现 AddLocalNotification 接口 PushResult 的回调 |
步骤3:配置通知
本地通知
调用 AddLocalNotification
接口。
远程推送
发送推送通知到所有设备:
- 在游戏 里调用
RegisterPush
接口,然后终止游戏。 - 在 Firebase 的后台选择 Cloud Messaging,然后点击 新建通知。
- 填写通知标题和文字,然后点击 下一步。
- 选择要发到应用的 bundle,然后点击 下一步。
- 选择时间,然后点击 审核。
- 审核通过后则可以发送推送。
发送推送通知到 pushToken 注册设备:
- 在游戏里调用
RegisterPush
接口,然后把日志上的 FCM token 拷贝下来并终止游戏。 - 在 Firebase 的后台选择 Cloud Messaging,然后点击 新建通知。
- 填写通知标题和文字,然后点击 发送测试消息。
- 填写日志上的 FCM token,然后点击 测试 进行推送测试。
推送界面
清除 iOS app 角标
- Unity
- Unreal Engine
以下清除角标代码需添加到 Xcode 工程目录下 Classes/UnityAppController.mm
文件的 applicationDidBecomeActive
方法里。
[UIApplication sharedApplication].applicationIconBadgeNumber=0;
代码示例:
- (void)applicationDidBecomeActive:(UIApplication*)application
{
::printf("-> applicationDidBecomeActive()\n");
[self removeSnapshotView]; // 不同 Unity 版本间的代码可能有所不同
[UIApplication sharedApplication].applicationIconBadgeNumber=0; // 添加的代码
if (_unityAppReady)
{
if (UnityIsPaused() && _wasPausedExternal == false)
{
UnityWillResume();
UnityPause(0);
}
if (_wasPausedExternal)
{
if (UnityIsFullScreenPlaying())
TryResumeFullScreenVideo();
}
UnitySetPlayerFocus(1);
}
else if (!_startUnityScheduled)
{
_startUnityScheduled = true;
[self performSelector: @selector(startUnity:) withObject: application afterDelay: 0];
}
_didResignActive = false;
}
通过创建 XCodePostProcess.cs
脚本来自动添加代码。
- 将变量
code
赋值给EditorCode
方法中清除角标的代码。 - 通过锚点代码添加该方法。由于 Unity 版本不同,请确认
applicationDidBecomeActive
方法中是否调用了[self removeSnapshotViewController];
或[self removeSnapshotView];
,然后在步骤3中使用相应的结果。 - 根据步骤2的结果,配置
unityAppController.WriteBelow
。 - 在
OnPostProcessBuild
方法中调用EditorCode
。 - 检查已构建的
UnityAppController.mm
是否成功添加了清除角标的代码。
private static void EditorCode(string filePath)
{
// load UnityAppController.mm
UnityEngine.Debug.Log("EditorCode: " + filePath);
XClass unityAppController = new XClass(filePath + "/Classes/UnityAppController.mm");
//add codes
string codes = "[UIApplication sharedApplication].applicationIconBadgeNumber=0;"; // 添加的代码
unityAppController.WriteBelow("[self removeSnapshotViewController];", codes); // 添加的代码
}
在 INTLAppDelegate.mm
文件中的函数 Initialize
中添加注册回调。
FCoreDelegates::ApplicationHasReactivatedDelegate.AddStatic(&ApplicationHasReactivatedDelegate_Handler);
INTLAppDelegate.mm
文件新增函数。
static void ApplicationHasReactivatedDelegate_Handler()
{
[UIApplication sharedApplication].applicationIconBadgeNumber =0;
}
推送情况
不同场景下通知的显示行为:
状态 | iOS | Android |
---|---|---|
前 台 app | 不显示 | 不显示 |
后台 app | 显示 | 显示 |
退出 app | 显示 | 显示 |
iOS 10 及之后的系统,可以通过修改 userNotificationCenter:
、willPresentNotification:
、withCompletionHandler:
来实现显示到通知横幅,详见 Apple 开发者文档。
三星设备,用户需在系统内设置 设置 > 通知 > 休眠 为您的 app 添加自启动权限,以在 app 退出的状态下接收推送通知。
小米设备,在电池设置内的应用后台权限不能被限制,以在 app 退出的状态下接收推送通知。当 app 内存被清除时,已显示的通知也会随之消失。
不同场景下通知是否会有回调:
状态 | iOS | Android |
---|---|---|
前台 app | 有 | 有 |
后台 app | 无 | 无 |
点击通知 | 有 | 无 |
推送通知 API
- Unity
- Unreal Engine
API | Function |
---|---|
RegisterPush | 注册推送 |
UnregisterPush | 注销推送 |
AddLocalNotification | 添加本地通知 |
ClearLocalNotifications | 清空本地通知 |
DeleteLocalNotifications | 删除本地通知 |
API | Function |
---|---|
RegisterPush | 注册推送 |
UnregisterPush | 注销推送 |
AddLocalNotification | 添加 Android 本地通知 |
AddLocalNotificationIOS | 添加 iOS 本地通知 |
ClearLocalNotifications | 清空本地通知 |
DeleteLocalNotifications | 删除本地通知 |