Advanced Usage
Get SDK and Demo
- SDK Download: PC SDK Download Page
- Demo Project: GitHub - UnityMiniHost/PCDemo
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 filesscripts/- Build and run scriptsnative_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