跳到主要内容

Godot Push 通知 SDK (版本 1.2.0)

SDK 正常运行条件​

以下是 push 通知的工作条件。

重要
  • 应用程序不同类型版本(debug、release 等)的签名和包名(package name)可能互不相同。 在这种情况下,您必须在 RuStore 控制台 的“推送通知 > 项目”部分为每种版本类型创建一个项目。。
  • 正在使用最新版本的 SDK。
  • 已在 RuStore 控制台 的“推送通知 > 项目”部分上传应用程序数据。
  • 应用程序已通过审核(无需发布应用程序)。

    。
  • 用户设备上已安装最新版本的 RuStore。
  • RuStore 应用程序支持推送通知功能。
  • RuStore 应用程序已获准在后台运行。
  • 用户已在 RuStore 中登录。
  • 设备上安装的应用程序签名指纹与 RuStore 控制台 的“推送通知 > 项目”部分中添加的应用程序签名指纹一致。
  • Godot 4 版本 4.1.4。

实现示例​

请参阅 示例应用程序,以了解如何正确集成推送通知 SDK。

连接到项目​

  1. 从 GitFlic 上的 RuStore 官方仓库复制插件项目和示例应用程序项目。

  2. 在您的 IDE 中打开 godot_plugin_libraries 文件夹中的 Android 项目。

  3. 将 godot-lib.xxx.yyy.template_release.aar 包放入 godot_plugin_libraries/libs 文件夹中,其中 xxx.yyy 是您所使用的 Godot Engine 版本的版本号。

  4. 使用 gradle assemble 命令执行项目构建。

构建成功后,godot_example/android/plugins 文件夹中将创建以下文件:

  • RuStoreGodotPush.gdap;
  • RuStoreGodotPush.aar;
  • RuStoreGodotCore.gdap;
  • RuStoreGodotCore.aar。
警告

请特别注意,插件库必须针对您的 Godot Engine 版本进行构建。

  1. 将 godot_example/android/plugins 文件夹的内容复制到 your_project/android/plugins 文件夹中。
  2. 将 godot_example/android/build_example 文件夹的内容复制并替换到 godot_example/android/build 文件夹中。
  3. 在 Android 构建预设的插件列表中,勾选 Ru Store Godot Push 和 Ru Store Godot Core。

编辑应用清单文件​

在清单文件 your_project/android/build/AndroidManifest.xml 中,声明一个继承自 RuStoreMessagingService 的服务。

AndroidManifest.xml
<service
android:name="ru.rustore.godot.pushclient.RuStoreGodotMessagingService"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="ru.rustore.sdk.pushclient.MESSAGING_EVENT" />
</intent-filter>
</service>

如果需要更改标准通知的图标或颜色,请添加以下代码。

AndroidManifest.xml
<meta-data
android:name="ru.rustore.sdk.pushclient.default_notification_icon"
android:resource="@drawable/ic_baseline_android_24" />
<meta-data
android:name="ru.rustore.sdk.pushclient.default_notification_color"
android:resource="@color/your_favorite_color" />

如果需要重定义通知渠道,请添加以下代码。

AndroidManifest.xml
<meta-data
android:name="ru.rustore.sdk.pushclient.default_notification_channel_id"
android:value="@string/pushes_notification_channel_id" />

在添加 push 通知渠道时,您必须自行创建该渠道。

在 Android 13+ 中请求显示通知的权限​

Android 13 版本引入了一个用于显示 push 通知的新权限。 这将影响所有在 Android 13 或更高版本上运行并使用 RuStore Push SDK 的应用程序。

默认情况下,1.4.0 及更高版本的 RuStore Push SDK 在清单文件中包含了 POST_NOTIFICATIONS 权限。 但是,应用程序还需要在运行时通过 android.permission.POST_NOTIFICATIONS 常量请求此权限。 只有在用户授予权限后,应用程序才能显示 push 通知。

请求显示 push 通知的权限。

Activity/Fragment
// Declare the launcher at the top of your Activity/Fragment:
private final ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
if (isGranted) {
// RuStore Push SDK (and your app) can post notifications.
} else {
// TODO: Inform user that your app will not show notifications.
}
});

private void askNotificationPermission() {
// This is only necessary for API level>= 33 (TIRAMISU)
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
PackageManager.PERMISSION_GRANTED) {
// RuStore Push SDK (and your app) can post notifications.
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
// TODO: display an educational UI explaining to the user the features that will be enabled
// by them granting the POST_NOTIFICATION permission. This UI should provide the user
// "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
// If the user selects "No thanks," allow the user to continue without notifications.
} else {
// Directly ask for the permission
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
}
}

初始化​

初始化需要 来自 RuStore 控制台 的项目 ID。 要获取该 ID,请在应用程序页面中转到 推送通知 > 项目 部分,并复制 项目 ID 字段中的值。

img
请注意

请注意,Push SDK 不支持在多个进程中同时运行。
如果您的应用程序使用多个进程,则必须仅在主进程中初始化 SDK。

如果在辅助进程中进行初始化,可能会导致 push 通知工作异常。

插件初始化​

在调用库方法之前,需要先创建一个 RuStoreGodotPushClient 推送通知客户端对象。 请执行 init 方法来初始化客户端。

创建客户端
const PROJECT_ID = "123456"
const LOG_MODE = ERuStoreLogMode.Item.CUSTOM
const CLIENT_ID_TYPE = ERuStoreClientIdType.Item.GAID
const CLIENT_ID_VALUE = "your_client_id"

var _push_client: RuStoreGodotPushClient = null

func _ready:
_push_client = RuStoreGodotPushClient.get_instance()
_push_client.init(PROJECT_ID, LOG_MODE)
  • PROJECT_ID — 项目标识符。
  • LOG_MODE — 日志记录模式:
    • NONE — 不记录日志;
    • LOGCAT — 将消息输出到 logcat;
    • CUSTOM — 将消息输出到 on_log_* 事件中。

事件日志记录​

如果您想记录推送通知库的事件,请在初始化插件时将 LOG_MODE 设置为 ERuStoreLogMode.Item.CUSTOM,并执行一次事件订阅:

  • on_log_verbose;
  • on_log_debug;
  • on_log_info;
  • on_log_warn;
  • on_log_error。
on_log_* 事件
cfunc _ready:
# Инициализация _push_client

_push_client.on_log_verbose.connect(_on_log_verbose)
_push_client.on_log_debug.connect(_on_log_debug)
_push_client.on_log_info.connect(_on_log_info)
_push_client.on_log_warn.connect(_on_log_warn)
_push_client.on_log_error.connect(_on_log_error)

func _on_log_verbose(message: String):
pass

func _on_log_debug(message: String):
pass

func _on_log_info(message: String):
pass

func _on_log_warn(message: String):
pass

func _on_log_error(message: String):
pass

message —— 日志消息。

用户分群管理​

分群是指您根据特定参数选择的一组用户。 例如,带来最高收入的用户,或使用旧版本 Android 的用户。 有关分群的详细信息,请参阅 MyTracker 文档。

要开始使用分群,请在初始化 SDK 时指定 ClientIdType 和 ClientIdValue 参数。

创建客户端
const CLIENT_ID_TYPE = ERuStoreClientIdType.Item.GAID
const CLIENT_ID_VALUE = "your_client_id"

var _push_client: RuStoreGodotPushClient = null

func _ready:
_push_client = RuStoreGodotPushClient.get_instance()
_push_client.init(PROJECT_ID, LOG_MODE, CLIENT_ID_TYPE, CLIENT_ID_VALUE)
  • CLIENT_ID_TYPE — 标识符类型:
    • GAID — Google 广告标识符;
    • OAID — 华为广告标识符。
  • CLIENT_ID_VALUE — 标识符的值。

检查接收推送通知的能力​

Push 通知的工作条件请参阅“SDK 正确工作条件”章节。

若要检查分发应用程序是否已安装在用户设备上,请使用 check_push_availability 方法。

 在使用该方法之前,请先执行一次事件订阅:

  • on_check_push_availability_success;
  • on_check_push_availability_failure。
订阅事件
func _ready():
# Инициализация _push_client

_push_client.on_check_push_availability_success.connect(_on_check_push_availability_success)
_push_client.on_check_push_availability_failure.connect(_on_check_push_availability_failure)

func _on_check_push_availability_success(result: RuStoreFeatureAvailabilityResult):
pass

func _on_check_push_availability_failure(error: RuStoreError):
pass
调用 check_push_availability 方法
_push_client.check_push_availability()
  • 回调函数 (callback) on_check_push_availability_success 返回一个包含服务可用性信息的 RuStoreFeatureAvailabilityResult 对象。
RuStoreFeatureAvailabilityResult 类
class_name RuStoreFeatureAvailabilityResult extends Object

var isAvailable: bool = false
var cause: RuStoreError = null

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)
isAvailable = obj["isAvailable"]

if obj.has("cause"):
var jcause = JSON.stringify(obj["cause"])
cause = RuStoreError.new(jcause)
  • isAvailable — 接收 push 通知的条件是否满足:
    • true — 条件已满足;
    • false — 条件未满足。
  • cause — 错误信息。 RuStoreError 类的结构和所有可能的错误在错误处理章节中有所描述
  • 回调函数 (callback) on_check_push_availability_failure 返回一个包含所有其他错误的 RuStoreError 对象,例如—«无互联网连接»。 RuStoreError 类的结构在错误处理章节中有所描述。

Push 令牌操作方法​

获取用户的 Push 令牌​

警告

如果用户没有 push 令牌,该方法将创建并返回一个新的 push 令牌。

在初始化库之后,您可以使用 get_token 方法来获取当前用户的 push 令牌。

 在使用该方法之前,请先执行一次事件订阅:

  • on_get_token_success;
  • on_get_token_failure。
订阅事件
func _ready():
# Инициализация _push_client

_push_client.on_get_token_success.connect(_on_get_token_success)
_push_client.on_get_token_failure.connect(_on_get_token_failure)

func _on_get_token_success(data: String):
pass

func _on_get_token_failure(error: RuStoreError):
pass
调用 get_token 方法
_push_client.get_token()
  • 回调函数 (callback) on_get_token_success 将返回一个包含当前推送令牌 (push-token) 信息的字符串。

  • 回调函数 (callback) on_get_token_failure 将返回一个包含错误信息的 RuStoreError 对象。 RuStoreError 类的结构在错误处理章节中有所描述。

删除用户的 Push 令牌​

在初始化库之后,您可以使用 delete_token 方法来删除当前用户的 push 令牌。

 在使用该方法之前,请先执行一次事件订阅:

  • on_delete_token_success;
  • on_delete_token_failure。
订阅事件
func _ready():
# Инициализация _push_client

_push_client.on_delete_token_success.connect(_on_delete_token_success)
_push_client.on_delete_token_failure.connect(_on_delete_token_failure)

func _on_delete_token_success():
pass

func _on_delete_token_failure(error: RuStoreError):
pass
调用 delete_token 方法
_push_client.delete_token()

回调函数 (callback) on_delete_token_failure 将返回一个包含错误信息的 RuStoreError 对象。 RuStoreError 类的结构在错误处理章节中有所描述。

Push 主题操作方法​

订阅主题 Push 通知​

初始化库后,您可以使用 subscribe_to_topic 方法订阅主题。

 在使用该方法之前,请先执行一次事件订阅:

  • on_subscribe_to_topic_success;
  • on_subscribe_to_topic_failure。
订阅事件
func _ready():
# Инициализация _push_client

_push_client.on_subscribe_to_topic_success(_on_subscribe_to_topic_success)
_push_client.on_subscribe_to_topic_failure(_on_subscribe_to_topic_failure)

func _on_subscribe_to_topic_success():
pass

func _on_subscribe_to_topic_failure(error: RuStoreError):
pass
调用 subscribe_to_topic 方法
const TOPIC_NAME = "hello"

_push_client.subscribe_to_topic(TOPIC_NAME)

TOPIC_NAME — 主题名称。

回调函数 (callback) on_subscribe_to_topic_success 表示操作已成功完成。

回调函数 (callback) on_subscribe_to_topic_failure 会返回一个包含错误信息的 RuStoreError 对象。 RuStoreError 类的结构在错误处理章节中有所描述。

取消订阅主题 Push 通知​

初始化库后,您可以使用 unsubscribe_from_topic 方法取消订阅主题。

 在使用该方法之前,请先执行一次事件订阅:

  • on_unsubscribe_from_topic_success;
  • on_unsubscribe_from_topic_failure.
订阅事件
func _ready():
# Инициализация _push_client

_push_client.on_unsubscribe_from_topic_success(_on_unsubscribe_from_topic_success)
_push_client.on_unsubscribe_from_topic_failure(_on_unsubscribe_from_topic_failure)

func _on_unsubscribe_from_topic_success():
pass

func _on_unsubscribe_from_topic_failure(error: RuStoreError):
pass
};
调用 unsubscribe_from_topic 方法
const TOPIC_NAME = "hello"

_push_client.unsubscribe_from_topic(TOPIC_NAME)

TOPIC_NAME — 主题名称。

回调函数 (callback) on_unsubscribe_to_topic_success 表示操作已成功完成。

回调函数 (callback) on_unsubscribe_to_topic_failure 返回一个包含错误信息的 RuStoreError 对象。 RuStoreError 类的结构在错误处理章节中有所描述。

从 RuStore SDK 获取数据​

若要从 RuStore SDK 接收推送通知数据,请在创建客户端并初始化后,执行一次事件订阅:

  • on_new_token;
  • on_message_received;
  • on_deleted_messages;
  • on_error。
订阅事件
func _ready:
# Инициализация _push_client

_push_client.on_new_token.connect(_on_new_token)
_push_client.on_message_received.connect(_on_message_received)
_push_client.on_deleted_messages.connect(_on_deleted_messages)
_push_client.on_error.connect(_on_error)

func _on_new_token(data: String):
pass

func _on_message_received(data: Dictionary):
pass

func _on_deleted_messages():
pass

func _on_error(errors: Array):
pass
方法名称描述

on_new_token

在收到新的推送令牌(push token)时调用此方法。 调用此方法后,您的应用程序负责将新的推送令牌发送到自己的服务器。 该方法返回新令牌的值。

on_message_received

在收到新的推送通知时调用此方法。

如果 notification 对象中包含数据,RuStore SDK 将自动显示通知。 如果您不希望这样做,请使用 data 对象,并将 notification 保持为空。 无论如何,该方法都会被调用。

可以通过 data[data] 字段获取推送通知的 payload 。

on_deleted_messages

如果一条或多条推送通知未送达设备,则调用此方法。 例如,如果通知在送达前已过期。

在调用此方法时,建议与自己的服务器进行同步,以免丢失数据。

on_error

如果在初始化时发生错误,则调用此方法。 它返回一个包含错误对象的数组。

可能的错误:

  • UnauthorizedException — 用户未在 RuStore 中登录。 即使用户未在 RuStore 中登录,也可能不会出现此错误。 此行为在 Push SDK 中是动态管理的。 即使您的用户没有遇到此类错误,对其进行处理仍然是有意义的;
  • HostAppNotInstalledException — 用户设备上未安装 RuStore;
  • HostAppBackgroundWorkPermissionNotGranted — RuStore 没有后台运行权限。 此错误并非关键错误。 推送通知将继续送达,但效果不如授予后台运行权限时那样好。
所有可能的错误均在 错误处理 章节中描述。

通知结构​

完整通知的结构
func _on_message_received(data: Dictionary):
print("messageId: " + data["messageId"])
print("priority: " + data["priority"])
print("ttl: " + data["ttl"])
print("collapseKey: " + data["collapseKey"])
print("data: " + data["data"])
print("rawData: " + data["rawData"])
  • messageId — 消息的唯一 ID。 它是每条消息的标识符。
  • priority — 返回优先级值(目前不考虑)。 目前定义了以下选项:
    • 0 — UNKNOWN;
    • 1 — HIGH;
    • 2 — NORMAL。
  • ttl — Int 类型的 push 通知生存时间,单位为秒。
  • from — 用于识别通知来源的字段:
    • 对于发送到主题(topic)的通知,该字段显示主题名称;
    • 在其他情况下,显示服务令牌的一部分。
    。
  • collapseKey — 通知组的标识符(目前不考虑)。
  • data — 一个字典,其中可以传递通知的附加数据。
  • rawData — 以字节数组形式表示的 data 字典。
  • notification — 通知对象。
Notification 对象的结构
func _on_message_received(data: Dictionary):
print("title: " + data["notification_title"])
print("body: " + data["notification_body"])
print("channelId: " + data["notification_channelId"])
print("color: " + data["notification_color"])
print("icon: " + data["notification_icon"])
print("clickAction: " + data["notification_clickAction"])
print("imageUrl: " + data["notification_imageUrl"])
  • title — 通知标题。
  • body — 通知正文。
  • channelId — 用于指定发送通知的渠道。 适用于 Android 8.0 及更高版本。
  • imageUrl — 用于插入通知的图像直接链接。 图像大小不得超过 1 MB。
  • color — 以字符串形式表示的 HEX 格式通知颜色。 例如,#0077FF。
  • icon — 来自 res/drawable 的通知图标,以与资源名称一致的字符串格式表示。
    例如,res/drawable 中有一个 small_icon.xml 图标,可以通过 R.drawable.small_icon 在代码中访问。
    为了让图标在通知中显示,服务器必须在 icon 参数中指定 small_icon 的值
    。
  • clickAction — 点击通知时用于打开 Activity 的 intent action。

创建用于发送通知的渠道​

发送通知的渠道遵循以下优先级。

  • 如果推送通知中包含 channelId 字段,RuStore SDK 将把通知发送到指定的渠道。 您的应用程序必须提前创建此渠道。

  • 如果推送通知中没有 channelId 字段,但您的应用程序在 AndroidManifest.xml 中指定了渠道参数,则将使用该指定渠道。 您的应用程序必须提前创建此渠道。

  • 如果 push 通知中没有 channelId 字段,且 AndroidManifest.xml 中未指定默认通道,RuStore SDK 将创建该通道并将通知发送至其中。 此后,所有未明确指定通道的通知都将发送到该通道。

点击通知时打开 Activity​

默认情况下,点击通知时,RuStore SDK 将打开 action 为 android.intent.action.MAIN 的 activity。 如果存在 clickAction 字段,RuStore SDK 将打开符合指定 action 的 Intent filter 的 activity。

请在应用程序清单文件中,在 activity 相应的 <intent-filter> 元素中添加一行 <category android:name="android.intent.category.DEFAULT" />。 这是为了确保在点击通知时能默认打开 activity。 如果没有这一行,RuStore SDK 将无法打开 activity。

为了让 SDK 能够在不重启游戏的情况下打开 game activity,在点击推送通知进入应用程序时,需要清除 intent。 具体操作如下:

  1. 进入 your_project/android/build/src/com /godot/game 文件夹。

  2. 创建一个继承自 FullScreenGodotApp 的 GodotPushApp 类。

GodotPushApp 实现示例
package com.godot.game;

import org.godotengine.godot.FullScreenGodotApp;
import android.os.Bundle;

public class GodotPushApp extends FullScreenGodotApp {

@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.GodotAppMainTheme);
super.onCreate(savedInstanceState);
}
}
  1. 修改 GodotApp 类。
GodotApp 实现示例
package com.godot.game;

import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class GodotApp extends AppCompatActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.GodotAppMainTheme);
super.onCreate(savedInstanceState);

/**
* Processing intenss here
*/

Intent newIntent = new Intent(this, GodotPushApp.class);
startActivity(newIntent);
finish();
}
}
  1. 在 your_project/android/build/AndroidManifest.xml 清单文件中添加关于 GodotPushApp activity 的信息。
AndroidManifest.xml
<activity
android:name="com.godot.game.GodotPushApp"
android:label="@string/godot_project_name_string"
android:theme="@style/GodotAppSplashTheme"
android:launchMode="singleInstance"
android:excludeFromRecents="false"
android:exported="true"
android:screenOrientation="sensor"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:resizeableActivity="false"
tools:ignore="UnusedAttribute" >
</activity>
  1. 将 activity android:name=".GodotApp" 中的 android:launchMode="singleInstance" 修改为 android:launchMode="singleTask"。

错误处理​

错误结构
class_name RuStoreError extends Object

var description: String

func _init(json: String = ""):
if json == "":
description = ""
else:
var obj = JSON.parse_string(json)
description = obj["detailMessage"]
  • description — 错误描述。

以下是错误类:

  • RuStoreNotInstalledException — 用户设备上未安装 RuStore。
  • RuStoreOutdatedException — 用户设备上安装的 RuStore 版本不支持此 SDK。
  • RuStoreUserUnauthorizedException — 用户未在 RuStore 中登录。
  • RuStoreFeatureUnavailableException — RuStore 没有后台运行权限。
  • RuStoreException — RuStore 基础错误,其他错误均继承自此类。

另请参阅​