Client
.NET/Unity C++/Unreal/Cocos2d-x JavaScript/Cocos2d-js Godot 3 Godot 4 Java/Android Defold cURL REST Swift Dart/Flutter
Server
TypeScript Go Lua
应用程序内通知
# 借助应用程序內通知,可以方便地将消息广播给一个或多个用户。这些通知非常适合发送公告、警告或游戏内奖励及礼品通知。
通知可以存储到下次打开应用程序时被读取时为止,也可以推送通知,会只让一个连接的用户看到。您还可以使用通知在游戏中触发自定义操作,并改变客户端行为。
这些通知是在应用程序内查看的,因此它们非常适合推送在应用程序外查看的通知。
发送通知
# 您可以用服务器端代码向一个或多个用户发送通知。可将通知发送给游戏中的每个人 – 并非只有好友才能交换消息。服务器也隐式发送各种特定事件的许多通知。
每条通知有一个代码,这用于对其进行分类。您为通知选择的代码必须从 0
开始并向上增加。请参阅下方 保留消息代码。
通知有一个将被编码为 JSON 的内容对象。
发送后,可将通知标记为持久。只有当前连接到服务器的客户端(即在线用户)才会接收到非持久消息。如需要确保通知在被读取前永不丢失,在发送时应将其标记为持久的。
Server
1
2
3
4
5
6
7
8
9
10
11
12
13
local nk = require ( "nakama" )
local user_id = "user id to send to"
local sender_id = nil -- "nil" for server sent.
local content = {
item_id = "192308394345345" ,
item_icon = "storm_bringer_sword.png"
}
local subject = "You earned a secret item!"
local code = 1
local persistent = true
nk.notification_send ( user_id , subject , content , code , sender_id , persistent )
Server
1
2
3
4
5
6
7
8
9
10
11
subject := "You earned a secret item!"
content := map [ string ] interface {}{
"item_id" : "192308394345345" ,
"item_icon" : "storm_bringer_sword.png"
}
userID := "user id to send to"
senderID := "" // Empty string for server sent.
code := 1
persistent := true
nk . NotificationSend ( ctx , userID , subject , content , code , senderID , persistent )
Server
1
2
3
4
5
6
7
8
9
10
let receiverId = '4c2ae592-b2a7-445e-98ec-697694478b1c' ;
let subject = "You've unlocked level 100!" ;
let content = {
rewardCoins : 1000 ,
}
let code = 101 ;
let senderId = 'dcb891ea-a311-4681-9213-6741351c9994' // who the message if from
let persistent = true ;
nk . notificationSend ( receiverId , subject , content , code , senderId , persistent );
接收通知
# 可以为客户端连接时接收到的通知注册回调。只要客户端套接字保持连接,一旦接收到通知就会调用处理程序。当返回多条消息(进行批处理以提高性能)时,将为每条通知调用一次处理程序。
Client
1
2
3
4
socket . onnotification = ( notification ) => {
console . log ( "Received %o" , notification );
console . log ( "Notification content %s" , notification . content );
}
Client
1
2
3
4
5
socket . ReceivedNotification += notification =>
{
Console . WriteLine ( "Received: {0}" , notification );
Console . WriteLine ( "Notification content: '{0}'" , notification . Content );
};
Client
1
2
3
4
5
6
7
rtListener -> setNotificationsCallback ([]( const NNotificationList & notifications )
{
for ( auto & notification : notifications . notifications )
{
std :: cout << "Notification content " << notification . content << std :: cout ;
}
});
Client
1
2
3
4
5
6
7
8
9
SocketListener listener = new AbstractSocketListener () {
@Override
public void onNotifications ( final NotificationList notifications ) {
System . out . println ( "Received notifications" );
for ( Notification notification : notifications . getNotificationsList ()) {
System . out . format ( "Notification content: %s" , notification . getContent ());
}
}
};
Client
1
2
3
4
5
6
7
func _ready ():
# First, setup the socket as explained in the authentication section.
socket . connect ( "received_notification" , self , "_on_notification" )
func _on_notification ( p_notification : NakamaAPI . ApiNotification ):
print ( p_notification )
print ( p_notification . content )
Client
1
2
3
4
5
local group_id = "<group id>"
socket.on_notification ( function ( message )
print ( "Received notification!" )
pprint ( message )
end )
Code snippet for this language REST has not been found. Please choose another language to show equivalent examples.
Code snippet for this language cURL has not been found. Please choose another language to show equivalent examples.
列出通知
# 您可以列出用户离线时接收到的通知。这些通知在发送时被标记为“持久”。实际的逻辑取决于游戏或应用程序,但我们建议在客户端重新连接后检索通知。然后您可以在游戏或应用程序内显示 UI 以及此列表。
Client
1
2
curl -X GET "http://127.0.0.1:7350/v2/notification?limit=10" \
-H 'Authorization: Bearer <session token>'
Client
1
2
3
4
5
const result = await client . listNotifications ( session , 10 );
result . notifications . forEach ( notification => {
console . info ( "Notification code %o and subject %o." , notification . code , notification . subject );
});
console . info ( "Fetch more results with cursor:" , result . cacheable_cursor );
Client
1
2
3
4
5
var result = await client . ListNotificationsAsync ( session , 10 );
foreach ( var n in result . Notifications )
{
Console . WriteLine ( "Subject '{0}' content '{1}'" , n . Subject , n . Content );
}
Client
1
2
3
4
5
6
7
8
9
auto successCallback = []( NNotificationListPtr list )
{
for ( auto & notification : list -> notifications )
{
std :: cout << "Notification content " << notification . content << std :: endl ;
}
};
client -> listNotifications ( session , 10 , opt :: nullopt , successCallback );
Client
1
2
3
4
NotificationList notifications = client . listNotifications ( session , 10 ). get ();
for ( Notification notification : notifications . getNotificationsList ()) {
System . out . format ( "Notification content: %s" , notification . getContent ());
}
Client
1
2
3
4
5
6
var result : NakamaAPI . ApiNotificationList = yield ( client . list_notifications_async ( session , 10 ), "completed" )
if result . is_exception ():
print ( "An error occurred: %s " % result )
return
for n in result . notifications :
print ( "Subject ' %s ' content ' %s '" % [ n . subject , n . content ])
Client
1
2
3
4
5
GET /v2/notification?limit= 10
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
Client
1
2
3
4
5
6
7
8
local result = client.list_notifications ( 10 )
if result.error then
print ( result.message )
return
end
for _ , notification in ipairs ( result.notifications ) do
pprint ( notification )
end
一次可以成批检索 100 条以内通知的列表。要检索所有消息,应使用可缓存游标累积消息。您可以将此游标保留在客户端上,并在用户重新连接时使用它,以跟踪离线时他们可能错过的任何通知。
您一般需要一次仅列出 100 条通知,否则可能会导致用户疲劳。一个好的解决方案是当用户滚动到 UI 面板的底部时,让 UI 获取下 100 条通知。
Client
1
2
curl -X GET "http://127.0.0.1:7350/v2/notification?limit=100&cacheable_cursor=<cacheableCursor>" \
-H 'Authorization: Bearer <session token>'
Client
1
2
3
4
5
6
7
8
9
10
11
var allNotifications = [];
var accumulateNotifications = ( cursor ) => {
var result = await client . listNotifications ( session , 100 , cursor );
if ( result . notifications . length == 0 ) {
return ;
}
allNotifications . concat ( result . notifications . notifications );
accumulateNotifications ( result . cacheable_cursor );
}
accumulateNotifications ( "" );
Client
1
2
3
4
5
6
7
8
9
var result = await client . ListNotificationsAsync ( session , 100 );
if (! string . IsNullOrEmpty ( result . CacheableCursor ))
{
result = await client . ListNotificationsAsync ( session , 100 , result . CacheableCursor );
foreach ( var n in result . Notifications )
{
Console . WriteLine ( "Subject '{0}' content '{1}'" , n . Subject , n . Content );
}
}
Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// add to your class: std::vector<NNotification> allNotifications;
void YourClass :: accumulateNotifications ( const string & cursor )
{
auto successCallback = [ this ]( NNotificationListPtr list )
{
allNotifications . insert ( allNotifications . end (), list -> notifications . begin (), list -> notifications . end ());
if ( ! list -> cacheableCursor . empty ())
{
accumulateNotifications ( list -> cacheableCursor );
}
};
client -> listNotifications ( session , 100 , cursor , successCallback );
}
accumulateNotifications ( "" );
Client
1
2
3
4
5
6
7
NotificationList notifications = client . listNotifications ( session , 10 ). get ();
if ( notifications . getCacheableCursor () != null ) {
notifications = client . listNotifications ( session , 10 , notifications . getCacheableCursor ()). get ();
for ( Notification notification : notifications . getNotificationsList ()) {
System . out . format ( "Notification content: %s" , notification . getContent ());
}
}
Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var result : NakamaAPI . ApiNotificationList = yield ( client . list_notifications_async ( session , 1 ), "completed" )
if result . is_exception ():
print ( "An error occurred: %s " % result )
return
for n in result . notifications :
print ( "Subject ' %s ' content ' %s '" % [ n . subject , n . content ])
while result . cacheable_cursor and result . notifications :
result = yield ( client . list_notifications_async ( session , 10 , result . cacheable_cursor ), "completed" )
if result . is_exception ():
print ( "An error occurred: %s " % result )
return
for n in result . notifications :
print ( "Subject ' %s ' content ' %s '" % [ n . subject , n . content ])
print ( "Done" )
Client
1
2
3
4
5
GET /v2/notification?limit= 100& cursor = <cacheableCursor>
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
Client
1
2
3
4
5
6
7
8
9
10
11
12
13
local cursor = nil
repeat
local result = client.list_notifications ( 10 , cursor )
if result.error then
print ( result.message )
break
end
cursor = result.cursor
for _ , notification in ipairs ( result.notifications ) do
pprint ( notification )
end
until not cursor
这对于仅检索自上次客户端检索列表以来添加的通知很有用。可以用随每条列表消息返回的可缓存游标做到这一点。通过新的列表操作发送游标,将仅检索比已出现通知更晚的通知。
可缓存游标标记最近检索的通知的位置。我们建议您将可缓存游标存储在设备存储器中,并在客户端下次请求最近的通知时使用它。
Client
1
2
curl -X GET "http://127.0.0.1:7350/v2/notification?limit=10&cacheable_cursor=<cacheableCursor>" \
-H 'Authorization: Bearer <session token>'
Client
1
2
3
4
5
const cacheableCursor = "<cacheableCursor>" ;
const result = await client . listNotifications ( session , 10 , cacheableCursor );
result . notifications . forEach ( notification => {
console . info ( "Notification code %o and subject %o." , notification . code , notification . subject );
});
Client
1
2
3
4
5
6
const string cacheableCursor = "<cacheableCursor>" ;
var result = await client . ListNotificationsAsync ( session , 10 , cacheableCursor );
foreach ( var n in result . Notifications )
{
Console . WriteLine ( "Subject '{0}' content '{1}'" , n . Subject , n . Content );
}
Client
1
2
3
4
5
6
7
8
9
10
auto successCallback = []( NNotificationListPtr list )
{
for ( auto & notification : list -> notifications )
{
std :: cout << "Notification content " << notification . content << std :: endl ;
}
};
string cacheableCursor = "<cacheableCursor>" ;
client -> listNotifications ( session , 10 , cacheableCursor , successCallback );
Client
1
2
3
4
5
String cacheableCursor = "<cacheableCursor>" ;
NotificationList notifications = client . listNotifications ( session , 10 , cacheableCursor ). get ();
for ( Notification notification : notifications . getNotificationsList ()) {
System . out . format ( "Notification content: %s" , notification . getContent ());
}
Client
1
2
3
4
5
6
7
var cursor = "<cacheable-cursor>" ;
var result : NakamaAPI . ApiNotificationList = yield ( client . list_notifications_async ( session , 10 , cursor ), "completed" )
if result . is_exception ():
print ( "An error occurred: %s " % result )
return
for n in result . notifications :
print ( "Subject ' %s ' content ' %s '" % [ n . subject , n . content ])
Client
1
2
3
4
5
GET /v2/notification?limit= 10& cursor = <cacheableCursor>
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
Client
1
2
3
4
5
6
7
8
9
10
local cursor = "<cacheable-cursor>"
local result = client.list_notifications ( 10 , cursor )
if result.error then
print ( result.message )
return
end
for _ , notification in ipairs ( result.notifications ) do
pprint ( notification )
end
删除通知
# 您可以从客户端删除一条或多条通知。这有助于清除用户已读取或使用的通知,并防止旧消息的积累。删除通知后,会从系统中删除该通知的所有记录,并且无法恢复该通知。
Client
1
2
curl -X DELETE "http://127.0.0.1:7350/v2/notification?ids=<notificationId>&ids=<notificationId>" \
-H 'Authorization: Bearer <session token>'
Client
1
2
const notificationIds = [ "<notificationId>" ];
await client . deleteNotifications ( session , notificationIds );
Client
1
2
var notificationIds = new [] { "<notificationId>" };
await client . DeleteNotificationsAsync ( session , notificationIds );
Client
1
client -> deleteNotifications ( session , { "<notificationId>" });
Client
1
2
String [] notificationIds = new String [] { "<notificationId>" };
client . deleteNotifications ( session , notificationIds ). get ();
Client
1
2
3
4
5
6
var notification_ids = [ "<notification-id>" ]
var delete : NakamaAsyncResult = yield ( client . delete_notifications_async ( session , notification_ids ), "completed" )
if delete . is_exception ():
print ( "An error occurred: %s " % delete )
return
print ( "Deleted" )
Client
1
2
3
4
5
DELETE /v2/notification?ids= <notificationId>& ids = <notificationId>
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
Client
1
2
3
4
5
6
local ids = { "<notification-id>" }
local result = client.delete_notifications ( ids )
if result.error then
print ( result.message )
return
end
通知代码
# 对于就某些事件隐式发送的消息,服务器保留所有小于或等于 0 的代码。您只需使用大于 0 的值即可定义自己的通知代码。
该代码有助于决定如何在 UI 中显示通知。
代码 用途 0 保留 -1 离线或不在频道中时接收到的用户 X 的消息。 -2 用户 X 想要将您添加为好友。 -3 用户 X 接受了您的好友邀请。 -4 您已被接收进 X 群组。 -5 用户 X 想要加入您的群组。 -6 您的好友 X 加入了游戏。 -7 到套接字的最后通知通过single_socket
配置 关闭。