Skip to main content

Advanced Usage

Get SDK and Demo

1. Custom JsApi Handling​

1.1 Implementing JsApi Handler​

The SDK allows you to implement custom JsApi handlers to respond to API calls from games.

Basic Implementation Pattern:

// 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 Implementing Authentication Handler​

Example: Unity Connect Authentication


// 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 Request Implementation

For specific HTTP request implementations (WinHTTP on Windows, libcurl on macOS), please refer to the demo_http.cpp file in the Demo Project.


2. Event Listening and Handling​

2.1 Implementing Event Handler​

// 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. Core Service Event Handling​

3.1 Implementing 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);
String Processing Utilities

For JSON parsing and string escaping helper functions, please refer to the demo_utils.cpp file in the Demo Project.


4. Async Operations and State Management​

4.1 Using Callbacks to Manage State​

// 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. Complete Example​

The complete C++ SDK example project can be obtained from GitHub:

GitHub Repository: UnityMiniHost/PCDemo

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

The project includes:

  • demo.cpp - Complete implementation example (1100+ lines)
  • include/ - SDK header files
  • scripts/ - Build and run scripts
  • native_sdk/ - Pre-packaged SDK and runtime

Key implementation points:

  • Platform-specific HTTP request implementations (WinHTTP / libcurl)
  • Custom JsApi handlers (TJLoginHost, loadRewardAd, showRewardAd)
  • Event handling and state management
  • Cross-platform library loading and resource cleanup

Quick Run:

# Windows
scripts\build-and-run.bat

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