跳到主要内容

高级用法

获取 SDK 和 Demo

1. 自定义 JsApi 处理​

1.1 实现 JsApi 处理器​

SDK 允许您实现自定义的 JsApi 处理器来响应游戏中的 API 调用。

基本实现模式:

// Global applet manager reference for use in handler
static IAppletManagerV3* g_appletManager = nullptr;

// Main JsApi handler - dispatches to specific handlers
bool OnJsApiHandler(const char* app_id, const char* api_name,
const char* data, size_t data_size, int task_id) {
std::cout << "[JsApiHandler] API called: " << api_name << std::endl;
std::cout << " App ID: " << app_id << std::endl;
std::cout << " Task ID: " << task_id << std::endl;
std::cout << " Data Size: " << data_size << std::endl;

std::string dataStr = (data && data_size > 0) ? std::string(data, data_size) : "";

// Dispatch to specific handler based on api_name
if (api_name) {
if (strcmp(api_name, "TJLoginHost") == 0) {
return HandleTJLoginHost(app_id, dataStr, task_id);
}
if (strcmp(api_name, "loadRewardAd") == 0) {
return HandleLoadRewardAd(app_id, dataStr, task_id);
}
if (strcmp(api_name, "showRewardAd") == 0) {
return HandleShowRewardAd(app_id, dataStr, task_id);
}
}

// API not handled - send not_handled response
std::string notHandledResponse = R"({"success":false,"errorCode":"NOT_HANDLED","error":"API not handled"})";
if (g_appletManager) {
g_appletManager->SendJsApiOrEventResponse(task_id, notHandledResponse.c_str(), notHandledResponse.length());
}

return false;
}

// Register the handler
appletManager->SetJsApiHandler(OnJsApiHandler);
g_appletManager = appletManager; // Store global reference

1.2 实现认证处理器​

示例:Unity Connect 认证


// Perform HTTP authentication
std::string PerformUnityConnectAuth(const std::string& accessToken) {
std::string encodedToken = UrlEncode(accessToken);
std::string url = "https://example.com/minihost?token=" + encodedToken;

// Use platform-specific HTTP library (WinHTTP on Windows, libcurl on macOS)
std::string responseBody = HttpGet(url);

// Extract LSToken from response
std::string lsToken = ExtractJsonStringValue(responseBody, "LSToken");

if (lsToken.empty()) {
throw std::runtime_error("LSToken not found in auth response");
}

return lsToken;
}

// TJLoginHost handler
bool HandleTJLoginHost(const char* app_id, const std::string& dataStr, int task_id) {
try {
std::string accessToken = ExtractJsonStringValue(dataStr, "accessToken");

if (accessToken.empty()) {
std::string errorResponse = R"({"success":false,"errorCode":"MISSING_TOKEN","error":"accessToken is required"})";
g_appletManager->SendJsApiOrEventResponse(task_id, errorResponse.c_str(), errorResponse.length());
return false;
}

std::string lsToken = PerformUnityConnectAuth(accessToken);

std::ostringstream responseOss;
responseOss << R"({"success":true,"result":{"code":")" << lsToken << R"("}})";
std::string successResponse = responseOss.str();

g_appletManager->SendJsApiOrEventResponse(task_id, successResponse.c_str(), successResponse.length());
return true;

} catch (const std::exception& e) {
std::ostringstream errorOss;
errorOss << R"({"success":false,"errorCode":"API_ERROR","error":")" << e.what() << R"("})";
std::string errorResponse = errorOss.str();
g_appletManager->SendJsApiOrEventResponse(task_id, errorResponse.c_str(), errorResponse.length());
return false;
}
}
HTTP 请求实现

HTTP 请求的具体实现(Windows 使用 WinHTTP,macOS 使用 libcurl)请参考 Demo 项目 中的 demo_http.cpp 文件。


2. 事件监听和处理​

2.1 实现事件处理器​

// Event handler - called when game sends an event
bool OnEventHandler(const char* event_name, const char* data, size_t data_size, int task_id) {
std::cout << "[EventHandler] Event received: " << event_name << std::endl;
std::cout << " Task ID: " << task_id << std::endl;
std::cout << " Data Size: " << data_size << std::endl;

if (data && data_size > 0) {
std::cout << " Data: " << std::string(data, data_size) << std::endl;
}

// Handle specific events
if (event_name && strcmp(event_name, "game_exited") == 0) {
std::cout << "[EventHandler] Game exited" << std::endl;
// Handle game exit
return true;
}

return true; // Indicate event was handled
}

// Register event handler
appletManager->SetAppletEventHandler(OnEventHandler);

3. 核心服务事件处理​

3.1 实现 ICoreServiceHandler​

class DemoCoreServiceHandler : public ICoreServiceHandler {
public:
// COM interface methods (for stack objects, no ref counting needed)
virtual INT QueryInterface(const char* type, void** ppvObject) override {
return -1; // Not implemented
}

virtual ULONG AddRef(void) override {
return 1; // No-op for stack objects
}

virtual ULONG Release(void) override {
return 1; // No-op for stack objects
}

// Service lifecycle events
virtual void OnContextInitialized() override {
std::cout << "[CoreServiceHandler] Context initialized" << std::endl;
}

virtual void OnServiceDisconnected() override {
std::cout << "[CoreServiceHandler] Service disconnected" << std::endl;
// Handle service disconnection
}

virtual bool OnCommonEventHappened(const char* event_name, int32_t callback_id,
const char* data, const unsigned int data_size) override {
std::cout << "[CoreServiceHandler] Event: " << event_name << std::endl;

// Check for server process exit event
if (event_name && strcmp(event_name, "cservice_event_report_process") == 0) {
if (data && strstr(data, "\"event\":2")) {
std::cout << "[CoreServiceHandler] Server process exiting" << std::endl;
// Handle server exit
}
}

return true;
}
};

// Usage
DemoCoreServiceHandler handler;
service->InitializeBrowsingCore(config, runtimePath, &handler);
字符串处理工具

JSON 解析和字符串转义的辅助函数请参考 Demo 项目 中的 demo_utils.cpp 文件。


4. 异步操作和状态管理​

4.1 使用回调管理状态​

// Global state for launch result
static volatile bool g_launchCompleted = false;
static volatile int g_launchResultCode = -1;
static volatile bool g_shouldExit = false;

// Launch callback
void OnLaunchComplete(const char* appId, int resultCode, const char* errorDesc) {
std::cout << "[LaunchCallback] Launch finished!" << std::endl;
std::cout << " App ID: " << appId << std::endl;
std::cout << " Result Code: " << resultCode << std::endl;

if (errorDesc && strlen(errorDesc) > 0) {
std::cout << " Error: " << errorDesc << std::endl;
}

g_launchCompleted = true;
g_launchResultCode = resultCode;

if (resultCode != 0) {
g_shouldExit = true;
}
}

// Wait for launch with timeout
int launchWaitTime = 0;
const int launchTimeout = 30000; // 30 seconds
const int checkInterval = 500; // Check every 500ms

while (!g_launchCompleted && launchWaitTime < launchTimeout) {
std::this_thread::sleep_for(std::chrono::milliseconds(checkInterval));
launchWaitTime += checkInterval;

if (g_shouldExit) {
std::cerr << "Launch failed, exiting..." << std::endl;
break;
}
}

if (!g_launchCompleted) {
std::cerr << "Launch timeout after " << launchTimeout / 1000 << " seconds" << std::endl;
}

5. 完整示例​

完整的 C++ SDK 示例项目可从 GitHub 获取:

GitHub 仓库: UnityMiniHost/PCDemo

git clone https://github.com/UnityMiniHost/PCDemo.git
cd PCDemo

项目包含:

  • demo.cpp - 完整实现示例(1100+ 行)
  • include/ - SDK 头文件
  • scripts/ - 构建和运行脚本
  • native_sdk/ - 预打包的 SDK 和运行时

关键实现要点:

  • 平台相关的 HTTP 请求实现(WinHTTP / libcurl)
  • 自定义 JsApi 处理器(TJLoginHost, loadRewardAd, showRewardAd)
  • 事件处理和状态管理
  • 跨平台库加载和资源清理

快速运行:

# Windows
scripts\build-and-run.bat

# macOS
./scripts/build-and-run.sh

6. 相关文档​