消息存储 SDK 接入指南
消息存储 SDK 接入指南
本教程旨在使用 Push Message Storage SDK 来实现本地存储和查看历史聊天记录的功能
1. 安装配置 UOS Launcher
参考 Launcher 教程,安装 Launcher 后,关联 UOS APP, 开启 Push 服务并安装 Push Storage SDK。
Push Storage SDK 是一个独立于Push SDK的package, 当不需要使用消息存储服务时,可以仅安装Push SDK,安装Push Storage SDK会自动安装Push SDK
注意: 请务必确认在进行后续教程之前,已经成功完成了 Launcher 教程的安装步骤,否则可能导致后续接入无法顺利进行。
2.核心类&接口
/// <summary>
/// 保存一条消息到本地, 如果isReceived 为 false, 即当前玩家发送消息给指定玩家时,会自动标记消息已读。接收指定玩家的消息,会标记为未读。
/// </summary>
/// <param name="playerId"> 对方玩家Id</param>
/// <param name="content"> 消息内容</param>
/// <param name="isReceived"> 是否是接收到的消息,如果是则代表为接收来自<参数playerId/>的玩家消息,否则代表当前玩家发送给<参数playerId/>的消息</param>
/// <param name="playerName"> 对方玩家名称, 可选</param>
/// <exception cref="PushMessageStorageException">异常原因见exception的 errCode 和 message</exception>
UniTask SaveMessageAsync(string playerId, string content, bool isReceived, string playerName = "");
/// <summary>
/// 获取所有联系人的对话摘要(含最后消息和未读计数)
/// </summary>
/// <exception cref="PushMessageStorageException">异常原因见exception的 errCode 和 message</exception>
/// <returns>所有联系人的对话摘要列表</returns>
UniTask<List<ConversationSummary>> GetConversationSummariesAsync();
/// <summary>
/// 获取与某位玩家的全部聊天记录(按时间倒序)
/// </summary>
/// <param name="playerId"> 玩家Id</param>
/// <param name="pageSize"> 每页数量。默认50,最大50</param>
/// <param name="pageNumber"> 页码。默认1</param>
/// <exception cref="PushMessageStorageException">异常原因见exception的 errCode 和 message</exception>
/// <returns>与指定玩家的全部聊天记录(分页展示)</returns>
UniTask<PagedResult<MessageRecord>> GetMessagesByPlayerIdAsync(string playerId, int pageSize = 50, int pageNumber = 1);
// <summary>
/// 删除与某位玩家的全部聊天记录
/// </summary>
/// <param name="playerId"> 玩家Id</param>
/// <exception cref="PushMessageStorageException">异常原因见exception的 errCode 和 message</exception>
UniTask DeleteMessagesByPlayerIdAsync(string playerId);
/// <summary>
/// 标记与某玩家的全部消息为已读
/// </summary>
/// <param name="playerId"> 玩家Id</param>
/// <exception cref="PushMessageStorageException">异常原因见exception的 errCode 和 message</exception>
UniTask MarkAllAsReadAsync(string playerId);
/// <summary>
/// 获取某个玩家的未读消息数量
/// </summary>
/// <param name="playerId"> 玩家Id</param>
/// <exception cref="PushMessageStorageException">异常原因见exception的 errCode 和 message</exception>
/// <returns>与指定玩家的未读消息数量</returns>
UniTask<int> GetUnreadCountAsync(string playerId);3.集成示例
初始化SDK
/// <summary>
/// 创建消息存储SDK实例
/// </summary>
/// <param name="messageStorageType"> 存储方式,默认值为 sqlite。 注:当前仅支持sqlite</param>
/// <param name="dbPath"> 存储路径, 默认值为 UnityEngine.Application.persistentDataPath/message_storage.db。 推荐存储在 UnityEngine.Application.persistentDataPath目录下面, 该路径支持持久化存储,</param>
/// <param name="messageRetentionDays"> 消息保存天数,默认值为 0,即永久存储。更改后,会在初始化SDK实例时清除过期的消息记录, 且游戏期间每1小时清理一次过期聊天记录</param>
public static IMessageStorage Create(MessageStorageType messageStorageType, string dbPath, int messageRetentionDays);初始化示例:
try
{
// 使用默认参数创建一个持久化存储,消息永久保存的sdk 实例
var _storage = MessageStorageFactory.Create();
}
catch (PushMessageStorageException e)
{
Debug.LogErrorFormat("Failed to create message storage sdk instance. ex {0}", e);
throw;
}保存消息
在使用 Push SDK 给某个玩家发送一条消息后,或是 onMessage 方法响应收到来自其他玩家的消息后,可以调用该方法保存消息
// 示例演示在 Push SDK OnMessage 方法中收到来自 Player 消息时调用 SaveMessageAsync 存储消息
private async void OnMessage(PushMessage message)
{
// 判断非频道消息
if (message.ChannelName == "")
{
// 可自行通过消息内容判断是否是通知类消息(如邀请对战,好友请求等类型消息,这种类型消息可能不需要保存)
...
var playerId = message.SenderId; // 消息发送玩家id
var content = message.Data; // 消息内容
var isReceived = true; // 该值为true代表这是一条其他玩家发送过来的消息, 如果为false, 则代表是当前玩家发送给其他玩家的消息(发送出去的消息会默认标记已读)
try
{
// 保存一条消息到本地(默认未读)
await _storage.SaveMessageAsync(playerId, content, isReceived);
}
catch (PushMessageStorageException ex)
{
Debug.LogErrorFormat("存储消息失败 {0}", ex);
throw
}
}
}查看所有会话摘要
玩家登入游戏后,可通过该方法获取到所有会话的最近一条消息,以及每个会话的未读消息数量,用于展示在聊天界面。
public class ConversationSummary
{
/// <summary>对方玩家Id</summary>
public string PlayerId { get; set; }
/// <summary>对方玩家名字</summary>
public string PlayerName { get; set; }
/// <summary>是否是接收到的消息,如果是,代表为接收来自<成员变量playerId/>的玩家消息,否则代表当前玩家发送给<成员变量playerId/>的消息</summary>
public bool IsReceived { get; set; }
/// <summary>最后一条消息内容</summary>
public string LastMessageContent { get; set; }
/// <summary>最后一条消息Unix时间戳</summary>
public long LastMessageTimestamp { get; set; }
/// <summary>未读消息数</summary>
public int UnreadCount { get; set; }
}
try
{
// summaries 结构为 List<ConversationSummary>
var summaries = await _storage.GetConversationSummariesAsync();
}
catch (PushMessageStorageException ex)
{
Debug.LogErrorFormat("获取所有会话摘要失败 {0}", ex);
throw;
}获取与指定玩家的所有消息
上一步获取所有会话摘要后,如玩家点击与某个玩家的聊天框,则通过该方法获取与指定玩家的所有聊天记录。
try
{
var playerId = "<playerId>"; // 玩家id
var pageSize = 50; // 每页数量,最大50
var pageNumber = 1; // 页码
var messages = await _storage.GetMessagesByPlayerIdAsync(playerId, pageSize, pageNumber);
Debug.Log($"消息总条数: {messages.TotalCount}");
Debug.Log($"消息列表: {JsonConvert.SerializeObject(messages.Items)}");
}
catch (PushMessageStorageException ex)
{
Debug.LogErrorFormat("获取指定用户的所有消息失败 {0}", ex);
throw;
}标记已读
在玩家查看与指定玩家的所有聊天记录后,如与该玩家有未读消息,则可通过该方法标记与该玩家的所有聊天消息已读
try
{
var playerId = "<playerId>"; // 玩家id
await _storage.MarkAllAsReadAsync(playerId);
}
catch (PushMessageStorageException ex)
{
Debug.LogErrorFormat("标记消息已读失败 {0}", ex);
throw;
}删除与指定玩家的所有消息
try
{
var playerId = "<playerId>"; // 玩家id
await _storage.DeleteMessagesByPlayerIdAsync(playerId);
}
catch (PushMessageStorageException ex)
{
Debug.LogErrorFormat("删除指定玩家消息失败 {0}", ex);
throw;
}更多
更多SDK使用示例可参考Push Message Storage Demo
4.异常类
PushStorageMessage SDK 对外的异常被包装为 PushMessageStorageException,使用该SDK方法时只需要捕获该异常即可
public class PushMessageStorageException : Exception
{
public PushMessageStorageErrorCode ErrorCode { get; }
...
}
public enum PushMessageStorageErrorCode
{
/// <summary>系统未捕获的底层异常(默认错误类型),可查看详细exception message确认异常原因</summary>
GeneralFailure = 0,
/// <summary>数据库被锁定(SQLite BUSY状态),可稍后重试</summary>
DatabaseBusy = 1,
/// <summary>查询的记录不存在</summary>
RecordNotFound = 2,
/// <summary>违反数据库约束(唯一键/非空等)</summary>
ConstraintViolation = 3,
/// <summary>数据库连接失败</summary>
ConnectionFailed = 5,
/// <summary>操作被取消,比如查询过程中方法被取消调用</summary>
OperationCanceled,
/// <summary>未知错误类型</summary>
Unknown,
}