推送
Player Network SDK 的推送模块为游戏提供推送通知服务。推送功能分为本地通知和远程推送两种。本地通知功能使游戏在不运行的情况下也能向用户发送推送通知,如节日活动和周年纪念活动等。
Android 12 及以上系统,因 Android API 对 SCHEDULE_EXACT_ALARM
权限申请的收紧,Player Network SDK 使用了内部延时触发来实现推送。因此在关闭 app 后将无法触发延时代码。触发时间也因系统休眠策略会有误差。
前提条件
开始使用 本地通知 只需 接入 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。
Firebase 需要访问网络的权限。
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
工程配置
在 INTLConfig.ini 文件中配置 Android client key。
[Google]
GOOGLE_CLIENT_KEY_ANDROID = {YOUR_CLIENT_KEY_ANDROID}
- 替换
{YOUR_CLIENT_KEY_ANDROID}
为 Player Network SDK 需要的 Web client key,配置 API OAuth 时在 Credentials 页面的网页客户端对应的客户端 ID。即 OAuth 2.5 后台 API 配置的建立 OAuth 操作中的 Server Client ID。
google-services.json
没有 google-services.json
文件会导致打包失败。
Gradle 打包方式支持从 google-services.json
文件直接读取内容,转化成对应的 app/build/generated/res/google-services/{build_type}/values/values.xml
配置文件。
- Unity
- Unreal Engine
有关在项目的 Assets/Plugins/Android/
目录下添加 google-services.json
文件的更多详情,请参见 The Google Services Gradle Plugin。
有关在项目的 Assets/Plugins/Android/
目录下添加 google-services.json
文件的更多详情,请参见 The Google Services Gradle Plugin。
[可选] 配置默认背景颜色
在配置通知时指定颜色,使用该颜色作为通知横幅的默认背景颜色。
可以在 Unity 的 Assets/Plugins/Android/
目录下的 Android 工程目录下资源文件中定义 color
。
例如:xxx/res/values/colors.xml。
``` xml
<!-- 设置推送通知的颜色,当推送通知本身没有设置颜色时使用。
更多信息,请参见 README(https://goo.gl/6BKBk7)。 -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
```
[可选] 配置默认图标
在配置通知时指定图标,使用该图标作为通知的默认图标。
可以在 Unity 的 Assets/Plugins/Android/
目录下的 Android 工程目录下放置 drawable
文件。
例如:xxx/res/drawable。
```xml
<!-- 设置自定义默认图标,当推送通知本身未设置图标时使用。
更多信息请参见 README(https://goo.gl/l4GJaQ)。 -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_ic_notification" />
```
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 V4.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 | 删除本地通知 |