| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- using System;
- using System.Runtime.InteropServices;
- using System.Text;
- namespace TapSDK.CloudSave.Standalone
- {
- internal class TapCloudSaveWrapper
- {
- #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
- internal const string DllName = "cloudsave_sdk";
- #elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
- internal const string DllName = "libcloudsave_sdk";
- #endif
- /**
- * 初始化接口,只需要调用一次。非线程安全,并发调用可能崩溃。
- *
- * cfg 初始化配置,JSON 格式:
- *
- * TapSDK参数格式
- * {
- * "region": 2,
- * "log_to_console": 1,
- * "log_level": 3,
- * "data_dir": "/tmp",
- * "client_id": "***",
- * "client_token": "***",
- * "ua": "TapSDK-Android/3.28.0",
- * "lang": "zh-CN",
- * "platform": "Android",
- * "device_id": "123456",
- * "sdk_artifact": "Android",
- * "sdk_module_ver": "4.6.0",
- * "sdk_token": {
- * "kid": "***",
- * "key": "***"
- * }
- * }
- *
- *
- * - region 取值:0 国内、1 海外、2 RND、3 海外RND
- * - log_to_console 是否输出到控制台:0 不输出、1 输出。
- * - log_level 取值:1 Trace、2 Debug、3 Info、4 Warn、5 Error、6 完全不输出
- * - data_dir 保存本地缓存和日志文件的目录,不允许为空
- * - client_id 不允许为空
- * - client_token 不允许为空
- * - ua user agent,不允许为空
- * - lang 语言,允许为空
- * - platform 不允许为空,TapSDK专用参数
- * - device_id 设备ID,不允许为空,TapSDK专用参数
- * - sdk_artifact 不允许为空,TapSDK专用参数
- * - sdk_module_ver 不允许为空,TapSDK专用参数
- * - sdk_token 登录态鉴权token,允许为空,TapSDK专用参数
- * - kid mac_key id,不允许为空
- * - key mac密钥,不允许为空
- * - runtime_ver 宿主版本,不允许为空,Tap Miniapp专用参数
- * - access_token 登录态鉴权token,允许为空,Tap Miniapp专用参数
- * - kid mac_key id,不允许为空
- * - key mac密钥,不允许为空
- *
- * 成功返回 0,失败返回 -1
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern int TapSdkCloudSaveInitialize(string cfg);
- /**
- * 用于释放TapSdkCloudSaveCreateArchive、TapSdkCloudSaveGetArchiveList、TapSdkCloudSaveGetArchiveData等函数返回的堆内存
- *
- * @param data 需要释放的内存
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern void TapSdkCloudSaveFreeMemory(IntPtr intPtr);
- /**
- * access token发生变化(比如切换账号)时调用。收到接口报access_denied错误时,SDK使用方需要重新登录,然后调用该接口更新access token
- *
- * @param token 最新的access token,传空指针或"{}"表示用户退出登录。格式如下:
- * {
- * "kid": "***",
- * "key": "***"
- * }
- *
- * @return 成功返回 0,失败(通常是JSON格式错误)返回 -1
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern int TapSdkCloudSaveUpdateAccessToken(string token);
- /**
- * 创建云存档,同步等待服务端返回,然后更新本地存档缓存。不允许并发调用,否则直接抛错
- *
- * @param metadata 存档元信息,JSON格式
- * {
- * "name": "存档名,60字节以内,不允许空,不允许汉字",
- * "summary": "存档描述,500字节以内,不允许空",
- * "extra": "用户自定义信息,1000字节以内,允许空",
- * "playtime": 0
- * }
- * - playtime 秒级
- * @param archiveData 存档二进制数据,不允许空指针
- * @param archiveDataSize saveData的大小(字节),不允许为0
- * @param coverData 封面二进制数据,允许空指针
- * @param coverDataSize saveData的大小(字节),允许为0
- * @param extraParams Tap Miniapp专用参数,JSON格式。其他接入方传空指针即可
- * {
- * "X-UA": "***",
- * "miniappId": "***"
- * }
- *
- * @return JSON格式,服务端生成的云存档UUID和FileID,或者错误信息。用完后,调用方需要调用TapSdkCloudSaveFreeMemory来释放内存
- * {
- * "data": {
- * "uuid": "存档UUID",
- * "file_id": "存档文件ID,用于下载文件"
- * },
- * "now": 1748340775,
- * "success": true
- * }
- * @note 对于Tap Miniapp,JSON字段使用驼峰风格。比如上面的返回示例,对于Tap Miniapp,是"fileId"而不是"file_id"。
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveCreateArchive(
- string metadata,
- byte[] archiveData,
- int archiveDataSize,
- byte[] coverData,
- int coverDataSize,
- string extraParams
- );
- /**
- * 更新云存档,同步等待服务端返回,然后更新本地存档缓存。不允许并发调用,否则直接抛错
- *
- * @param archiveUUID TapSdkCloudSaveCreateArchive()返回的云存档UUID,比如:"1bffaa173dde2e7afb5adf6442971961"。必须先创建云存档成功后,通过云存档UUID来更新
- * @param metadata 存档元信息,JSON格式
- * {
- * "name": "存档名,60字节以内,不允许空,不允许汉字",
- * "summary": "存档描述,500字节以内,不允许空",
- * "extra": "用户自定义信息,1000字节以内,允许空",
- * "playtime": 0
- * }
- * - playtime 秒级
- * @param archiveData 存档二进制数据,不允许空指针
- * @param archiveDataSize saveData的大小(字节),不允许为0
- * @param coverData 封面二进制数据,允许空指针
- * @param coverDataSize saveData的大小(字节),允许为0
- * @param extraParams Tap Miniapp专用参数,JSON格式。其他接入方传空指针即可
- * {
- * "X-UA": "***",
- * "miniappId": "***"
- * }
- *
- * @return JSON格式,服务端生成的云存档UUID和FileID,或者错误信息。用完后,调用方需要调用TapSdkCloudSaveFreeMemory来释放内存
- * {
- * "data": {
- * "uuid": "存档UUID",
- * "file_id": "存档文件ID,用于下载文件"
- * },
- * "now": 1748340775,
- * "success": true
- * }
- * @note 对于Tap Miniapp,JSON字段使用驼峰风格。比如上面的返回示例,对于Tap Miniapp,是"fileId"而不是"file_id"。
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveUpdateArchive(
- string archiveUUID,
- string metadata,
- byte[] archiveData,
- int archiveDataSize,
- byte[] coverData,
- int coverDataSize,
- string extraParams
- );
- /**
- * 发起删除存档请求,同步等待服务端返回,然后删除本地存档缓存。允许并发调用
- *
- * @param archiveUUID TapSdkCloudSaveCreateArchive()/TapSdkCloudSaveGetArchiveList()返回的云存档UUID,比如:"1bffaa173dde2e7afb5adf6442971961"。必须先创建云存档成功后,通过云存档UUID来删除
- * @param extraParams Tap Miniapp专用参数,JSON格式。其他接入方传空指针即可
- * {
- * "X-UA": "***",
- * "miniappId": "***"
- * }
- *
- * @return JSON格式,返回成功或者错误信息。用完后,调用方需要调用TapSdkCloudSaveFreeMemory来释放内存
- * {
- * "data": {
- * "uuid": "被删掉的云存档UUID"
- * },
- * "now": 1748487810,
- * "success": true
- * }
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveDeleteArchive(
- string archiveUUID,
- string extraParams
- );
- /**
- * 获取存档元信息列表,同步等待服务端返回。允许并发调用
- *
- * @param extraParams Tap Miniapp专用参数,JSON格式。其他接入方传空指针即可
- * {
- * "X-UA": "***",
- * "miniappId": "***"
- * }
- *
- * @return JSON格式,返回存档元信息列表,或者错误信息。用完后,需要调用TapSdkCloudSaveFreeMemory来释放内存
- * {
- * "data": {
- * "saves": [
- * {
- * "uuid": "738b6c08bdbe459b96607dd10f83d177",
- * "file_id": "738b6c08bdbe459b96607dd10f83d177",
- * "name": "save",
- * "save_size": 184237,
- * "cover_size": 7138,
- * "summary": "i love this game",
- * "extra": "what the hell",
- * "playtime": 0,
- * "created_time": 1748587677,
- * "modified_time": 1748587677
- * }
- * ]
- * },
- * "now": 1748588091,
- * "success": true
- * }
- * - playtime 秒级
- * @note 对于Tap Miniapp,JSON字段使用驼峰风格。比如上面的返回示例,对于Tap Miniapp,是"fileId/saveSize"而不是"file_id/save_size"。
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveGetArchiveList(string extraParams);
- /**
- * 读取存档文件,优先使用本地缓存,不存在才下载
- *
- * @param archiveUUID TapSdkCloudSaveCreateArchive()/TapSdkCloudSaveGetArchiveList()返回的云存档UUID,必须先创建云存档成功后,才能读取
- * @param archiveFileID TapSdkCloudSaveCreateArchive()/TapSdkCloudSaveGetArchiveList()返回的存档文件FileID,必须先创建云存档成功后,才能读取
- * @param archiveDataSize 出参,实际读取到的存档文件大小。如果读取失败,则其值会是负数
- * @param extraParams Tap Miniapp专用参数,JSON格式。其他接入方传空指针即可
- * {
- * "X-UA": "***",
- * "miniappId": "***"
- * }
- *
- * @return 成功时saveSize是实际读取到的存档文件大小,返回存档文件内容;失败时saveSize是负数,返回JSON格式的错误信息,格式如下。用完后,需要调用TapSdkCloudSaveFreeMemory来释放内存
- * {
- * "data": {
- * "code": -1,
- * "msg": "InvalidArgument: BINDING: Key: 'GetSavesRequest.uuid' Error:Field validation for 'uuid' failed on the 'len' tag",
- * "error": "invalid_request",
- * "error_description": "InvalidArgument: BINDING: Key: 'GetSavesRequest.uuid' Error:Field validation for 'uuid' failed on the 'len' tag"
- * },
- * "now": 1748915185,
- * "success": false
- * }
- * @note 对于Tap Miniapp,JSON字段使用驼峰风格。比如上面的返回示例,对于Tap Miniapp,是"errorDescription"而不是"error_description"。
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveGetArchiveData(
- string archiveUUID,
- string archiveFileID,
- out int archiveDataSize,
- string extraParams
- );
- /**
- * 读取封面文件,优先使用本地缓存,不存在才下载
- *
- * @param archiveUUID TapSdkCloudSaveCreateArchive()/TapSdkCloudSaveGetArchiveList()返回的云存档UUID,必须先创建云存档成功后,才能读取
- * @param archiveFileID TapSdkCloudSaveCreateArchive()/TapSdkCloudSaveGetArchiveList()返回的存档文件FileID,必须先创建云存档成功后,才能读取
- * @param coverSize 出参,实际读取到的封面文件大小。如果读取失败,则其值会是负数
- * @param extraParams Tap Miniapp专用参数,JSON格式。其他接入方传空指针即可
- * {
- * "X-UA": "***",
- * "miniappId": "***"
- * }
- *
- * @return 成功时coverSize是实际读取到的封面文件大小,返回cover文件内容;失败时coverSize是负数,返回JSON格式的错误信息,格式如下。用完后,需要调用TapSdkCloudSaveFreeMemory来释放内存
- * {
- * "data": {
- * "code": -1,
- * "msg": "InvalidArgument: BINDING: Key: 'GetSavesRequest.uuid' Error:Field validation for 'uuid' failed on the 'len' tag",
- * "error": "invalid_request",
- * "error_description": "InvalidArgument: BINDING: Key: 'GetSavesRequest.uuid' Error:Field validation for 'uuid' failed on the 'len' tag"
- * },
- * "now": 1748915185,
- * "success": false
- * }
- * @note 对于Tap Miniapp,JSON字段使用驼峰风格。比如上面的返回示例,对于Tap Miniapp,是"errorDescription"而不是"error_description"。
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveGetArchiveCover(
- string archiveUUID,
- string archiveFileID,
- out int coverSize,
- string extraParams
- );
- /**
- * 设置日志等级
- * - logLevel 日志等级:1 trace、2 debug、3 info、4 warn、5 error、> 5 不打日志。建议调试时设为1,正式版设为3。
- * - logToConsole 是否输出到控制台:0 不输出、1 输出。
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern void TapSdkCloudSaveSetLogLevel(int logLevel, int logToConsole);
- /**
- * 代码版本,如:1.2.5
- *
- * @return SDK版本号,全局静态变量,无需释放内存
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveVersion();
- /**
- * git commit 版本,如:98f5d81a0fdcab9a755878b3e825c2cb510e5196
- *
- * @return git commit版本,全局静态变量,无需释放内存
- */
- [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr TapSdkCloudSaveGitCommit();
- internal static string CreateArchive(
- string metadata,
- byte[] archiveData,
- int archiveDataSize,
- byte[] coverData,
- int coverDataSize
- )
- {
- IntPtr intPtr = TapSdkCloudSaveCreateArchive(
- metadata,
- archiveData,
- archiveDataSize,
- coverData,
- coverDataSize,
- null
- );
- try
- {
- string result = GetUTF8String(intPtr);
- return result;
- }
- finally
- {
- TapSdkCloudSaveFreeMemory(intPtr);
- }
- }
- internal static string UpdateArchive(
- string archiveUUID,
- string metadata,
- byte[] archiveData,
- int archiveDataSize,
- byte[] coverData,
- int coverDataSize
- )
- {
- IntPtr intPtr = TapSdkCloudSaveUpdateArchive(
- archiveUUID,
- metadata,
- archiveData,
- archiveDataSize,
- coverData,
- coverDataSize,
- null
- );
- try
- {
- string result = GetUTF8String(intPtr);
- return result;
- }
- finally
- {
- TapSdkCloudSaveFreeMemory(intPtr);
- }
- }
- internal static string DeleteArchive(string archiveUUID)
- {
- IntPtr intPtr = TapSdkCloudSaveDeleteArchive(archiveUUID, null);
- try
- {
- string result = GetUTF8String(intPtr);
- return result;
- }
- finally
- {
- TapSdkCloudSaveFreeMemory(intPtr);
- }
- }
- internal static string GetArchiveList()
- {
- IntPtr intPtr = TapSdkCloudSaveGetArchiveList(null);
- try
- {
- string result = GetUTF8String(intPtr);
- return result;
- }
- finally
- {
- TapSdkCloudSaveFreeMemory(intPtr);
- }
- }
- internal static byte[] GetArchiveData(
- string archiveUUID,
- string archiveFileID,
- out int archiveDataSize
- )
- {
- int dataSize = 0;
- IntPtr intPtr = TapSdkCloudSaveGetArchiveData(
- archiveUUID,
- archiveFileID,
- out dataSize,
- null
- );
- try
- {
- byte[] result;
- if (dataSize >= 0)
- {
- if (dataSize == 0)
- {
- result = new byte[0];
- }
- else
- {
- result = GetOriginByte(intPtr, dataSize);
- }
- }
- else
- {
- result = GetUTF8Byte(intPtr);
- }
- archiveDataSize = dataSize;
- return result;
- }
- finally
- {
- TapSdkCloudSaveFreeMemory(intPtr);
- }
- }
- internal static byte[] GetArchiveCover(
- string archiveUUID,
- string archiveFileID,
- out int coverSize
- )
- {
- int dataSize;
- byte[] result;
- IntPtr intPtr = TapSdkCloudSaveGetArchiveCover(
- archiveUUID,
- archiveFileID,
- out dataSize,
- null
- );
- try
- {
- coverSize = dataSize;
- if (dataSize >= 0)
- {
- if (dataSize == 0)
- {
- result = new byte[0];
- }
- else
- {
- result = GetOriginByte(intPtr, dataSize);
- }
- }
- else
- {
- result = GetUTF8Byte(intPtr);
- }
- return result;
- }
- finally
- {
- TapSdkCloudSaveFreeMemory(intPtr);
- }
- }
- private static string GetUTF8String(IntPtr ptr)
- {
- byte[] buffer = GetUTF8Byte(ptr);
- // 3. 按 UTF-8 解码
- return Encoding.UTF8.GetString(buffer);
- }
- private static byte[] GetUTF8Byte(IntPtr ptr)
- {
- // 1. 获取字符串长度(假设以 null 结尾)
- int len = 0;
- while (Marshal.ReadByte(ptr, len) != 0)
- {
- len++;
- }
- // 2. 复制字节到托管数组
- byte[] buffer = new byte[len];
- Marshal.Copy(ptr, buffer, 0, len);
- return buffer;
- }
- private static byte[] GetOriginByte(IntPtr ptr, int length)
- {
- byte[] copyByte = new byte[length];
- Marshal.Copy(ptr, copyByte, 0, length);
- return copyByte;
- }
- }
- }
|