// Unity to LogRocket iOS bridge. // // Uses __has_include so this file compiles whether or not the LogRocket pod is // integrated. When the pod is present the real, type-checked SDK calls compile // in; when absent every entry point degrades to a no-op so non-LogRocket builds // still link. // // To enable: add `pod 'LogRocket'` to the generated Podfile (or an EDM4U // *Dependencies.xml), run pod install, rebuild. API verified against the // LogRocket iOS SDK 3.x Objective-C surface (docs.logrocket.com/reference/ios): // LROSDK, LROConfiguration, LROCustomEventBuilder. // // NOTE: the LogRocket SDK is a Swift framework; its objects are ARC-managed. // Compile this file with ARC (-fobjc-arc). Unity's generated project enables // ARC by default; if you see leaks, confirm the flag on this file. #import #if __has_include() #import #define LR_AVAILABLE 1 #else #define LR_AVAILABLE 0 #endif static NSString* NSStr(const char* s) { return s ? [NSString stringWithUTF8String:s] : @""; } static NSDictionary* ParseJson(const char* json) { if (!json) return @{}; NSData* data = [NSStr(json) dataUsingEncoding:NSUTF8StringEncoding]; if (!data) return @{}; id obj = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; return [obj isKindOfClass:[NSDictionary class]] ? obj : @{}; } // Cached session URL. getSessionURL: is asynchronous and its handler may run on // a background thread, so we cache the latest value and hand the C# side a // snapshot. The first read may be NULL until the callback resolves. static NSString* gSessionUrl = nil; extern "C" { void _lr_init(const char* appId) { #if LR_AVAILABLE LROConfiguration* cfg = [[LROConfiguration alloc] initWithAppID:NSStr(appId)]; [LROSDK initializeWithConfiguration:cfg]; NSLog(@"[LogRocketBridge] initialized appId=%@", NSStr(appId)); #else NSLog(@"[LogRocketBridge] LogRocket pod not integrated - init no-op (appId=%@)", NSStr(appId)); #endif } void _lr_identify(const char* userId, const char* traitsJson) { #if LR_AVAILABLE [LROSDK identifyWithUserID:NSStr(userId) userInfo:ParseJson(traitsJson)]; #endif } void _lr_track(const char* eventName, const char* propsJson) { #if LR_AVAILABLE LROCustomEventBuilder* builder = [[LROCustomEventBuilder alloc] init:NSStr(eventName)]; // Property attachment uses the builder's put* API, whose exact selector names // are not pinned here. Events are tracked by name; wire props once the // installed SDK's LROCustomEventBuilder header is confirmed. [LROSDK track:builder]; #endif } void _lr_log(const char* severity, const char* message) { // The iOS SDK auto-captures application logs (NSLog/os_log), so emitting via // NSLog is enough for it to be recorded - no manual Logger call required. NSLog(@"[LogRocket:%@] %@", NSStr(severity), NSStr(message)); } void _lr_logException(const char* message, const char* stack) { NSLog(@"[LogRocket:error] %@\n%@", NSStr(message), NSStr(stack)); } void _lr_captureFrame(const void* bytes, int length, int width, int height) { // No-op: LogRocket iOS records the screen natively; there is no frame-ingest // API. Kept so the C# DllImport resolves. Disable the Unity frame loop // (LogRocketConfig.EnableSessionReplay = false) to avoid wasted work. (void)bytes; (void)length; (void)width; (void)height; } void _lr_startReplay(void) { // Recording starts automatically at initialize; nothing to do here. } void _lr_stopReplay(void) { #if LR_AVAILABLE [LROSDK shutdown]; #endif } const char* _lr_sessionUrl(void) { #if LR_AVAILABLE [LROSDK getSessionURL:^(NSString* url) { if (url) gSessionUrl = [url copy]; }]; #endif return gSessionUrl ? [gSessionUrl UTF8String] : NULL; } }