295 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
| // ==============================================
 | ||
| //  U3DConsent.mm
 | ||
| //  UnityFramework
 | ||
| //
 | ||
| //  Created by EricHu on 2022/11/17.
 | ||
| //  Copyright © 2022 guru. All rights reserved.
 | ||
| // ==============================================
 | ||
| 
 | ||
| #import <Foundation/Foundation.h>
 | ||
| #import "UnityAppController+UnityInterface.h"
 | ||
| #import <GuruAnalyticsLib/GuruAnalyticsLib-Swift.h>
 | ||
| 
 | ||
| @interface U3DAnalytics : NSObject
 | ||
| 
 | ||
| //+ (void)requestGDPR: (NSString *)deviceId :(int) debugGeo;
 | ||
| //+ (UIViewController *) getUnityViewController;
 | ||
| 
 | ||
| @end
 | ||
| 
 | ||
| static NSString *gameobjectName;
 | ||
| static NSString *callbackName;
 | ||
| 
 | ||
| static GuruAnalytics *_analytics;
 | ||
| 
 | ||
| 
 | ||
| @implementation U3DAnalytics
 | ||
| 
 | ||
| // Const value define
 | ||
| NSString * const Version = @"1.8.1";
 | ||
| 
 | ||
| static const double kUploadPeriodInSecond = 60.0;
 | ||
| static const int kBatchLimit = 15;
 | ||
| static const double kEventExpiredSeconds = 7 * 24 * 60 * 60;
 | ||
| static const double kInitializeTimeout = 5.0;
 | ||
| 
 | ||
| static double tch001MaxValue = 0.01;
 | ||
| static double tch02MaxValue = 0.2;
 | ||
| NSString * const TchAdRevRoas001 = @"tch_ad_rev_roas_001";
 | ||
| NSString * const TchAdRevRoas02 = @"tch_ad_rev_roas_02";
 | ||
| NSString * const TchError = @"tch_error";
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| +(UnityAppController *)GetAppController {
 | ||
|     return (UnityAppController*)[UIApplication sharedApplication].delegate;
 | ||
| }
 | ||
| 
 | ||
| +(UIViewController *) getUnityViewController {
 | ||
|     return UnityGetGLViewController();
 | ||
| }
 | ||
| 
 | ||
| // 字符串转换
 | ||
| +(const char*) stringToChar: (NSString *) str{
 | ||
|     return [str cStringUsingEncoding:NSASCIIStringEncoding];
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| +(NSString *) charToString: (const char *) c{
 | ||
|     return [[NSString alloc] initWithUTF8String:c];
 | ||
| }
 | ||
| 
 | ||
| // 获取最终字符串
 | ||
| +(char*) finalChar: (NSString *) string
 | ||
| {
 | ||
|     const char *tmpChar = [string cStringUsingEncoding:NSASCIIStringEncoding];
 | ||
|        
 | ||
|     if (string == NULL)
 | ||
|         return NULL;
 | ||
|     
 | ||
|     char* res = (char*)malloc(strlen(tmpChar) + 1);
 | ||
|     strcpy(res, tmpChar);
 | ||
|     
 | ||
|     return res;
 | ||
| }
 | ||
| 
 | ||
| // 设置太极02的预设值
 | ||
| +(void) setTch02MaxValue: (const double) value{
 | ||
|     tch02MaxValue = value;
 | ||
| }
 | ||
| 
 | ||
| // 构建数据
 | ||
| //+(NSString *) buildDataString: (int)status andMessage: (NSString *)msg{
 | ||
| //
 | ||
| //    NSString *jsonString = [NSString stringWithFormat: @"{\"action\":\"gdpr\",\"data\":{\"status\":%d,\"msg\":\"%@\"}}", status, msg];
 | ||
| //    return jsonString;
 | ||
| //}
 | ||
| 
 | ||
| // 构建数据字典
 | ||
| +(NSDictionary<NSString*, id> *) buildDataDict: (NSString *) str{
 | ||
|     
 | ||
|     NSArray *raw = [str componentsSeparatedByString:@","];
 | ||
|     if( raw == nil || raw.count == 0) return nil;
 | ||
|     
 | ||
|     NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; //must init before using
 | ||
|     
 | ||
|     for(NSString *s in raw ){
 | ||
|         NSArray *kvp = [s componentsSeparatedByString:@":"];
 | ||
|         if(kvp == nil || kvp.count  < 2){
 | ||
|             continue;
 | ||
|         }
 | ||
|         
 | ||
|         NSString *k = kvp[0];
 | ||
|         NSString *t = [kvp[1] substringToIndex:1];
 | ||
|         NSString *v = [kvp[1] substringFromIndex:1];
 | ||
|         
 | ||
|         // NSLog(@"---[iOS] parse kvp  key:%@  type:%@ value:%@", k, t, v);
 | ||
|         
 | ||
|         //TODO 解析字符值
 | ||
|         if([t isEqual: @"i"]){
 | ||
|             // int
 | ||
|             [dict setValue:@([v integerValue]) forKey:k];
 | ||
|         }else if([t isEqual: @"d"]){
 | ||
|             // double
 | ||
|             [dict setValue:@([v doubleValue]) forKey:k];
 | ||
|         } else {
 | ||
|             // String
 | ||
|             [dict setValue:v forKey:k];
 | ||
|         }
 | ||
|     }
 | ||
|     return dict;
 | ||
| }
 | ||
| 
 | ||
| // 构建Json格式的数据字典
 | ||
| +(NSMutableDictionary *) buildDataWithJson: (NSString *) json andKey: (NSString *) key{
 | ||
|     
 | ||
|     if( json == nil || json.length == 0) return nil;
 | ||
|     
 | ||
|     NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
 | ||
|     NSError *err;
 | ||
|     NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData
 | ||
|                                                         options:NSJSONReadingMutableContainers
 | ||
|                                                           error:&err];
 | ||
|     
 | ||
|     if(err || dict == nil)
 | ||
|     {
 | ||
|        NSLog(@"json解析失败:%@",err);
 | ||
|        [U3DAnalytics onTchErrorEvent:@"json_error" andRaw:json andOther:@""];
 | ||
|        return nil;
 | ||
|     }
 | ||
|     
 | ||
|     // ---------- 太极数据校验 -------------
 | ||
|     if(key == TchAdRevRoas001){
 | ||
|         // tch 001 参数修复
 | ||
|         [U3DAnalytics fixTchParams: dict andJson:json andMaxValue:tch001MaxValue];
 | ||
|     } else if(key == TchAdRevRoas02){
 | ||
|         // tch 02 参数修复
 | ||
|         [U3DAnalytics fixTchParams: dict andJson:json andMaxValue:tch02MaxValue];
 | ||
|     }
 | ||
|     
 | ||
|     return dict;
 | ||
| }
 | ||
| 
 | ||
| // 修复自打点数据
 | ||
| +(void) fixTchParams: (NSMutableDictionary *)dict andJson: (NSString *)json andMaxValue: (double) targetValue {
 | ||
|     // --- 保存 raw数据 ---
 | ||
|     [dict setValue: json forKey:@"raw"];
 | ||
|     
 | ||
|     id _platform = [dict objectForKey:@"ad_platform"];
 | ||
|     id _value = [dict objectForKey:@"value"];
 | ||
|     
 | ||
|     if([U3DAnalytics isNullObject: _platform]) {
 | ||
|         // 不存在 ad_paltform
 | ||
|         [U3DAnalytics onTchErrorEvent:@"no_ad_platform" andRaw:json andOther:@""];
 | ||
|     } else {
 | ||
|         // 非IAP订单
 | ||
|         if(![[_platform stringValue] isEqual:@"appstore"] )
 | ||
|         {
 | ||
|             if([U3DAnalytics isNullObject: _value] ){
 | ||
|                 [dict setValue: [NSNumber numberWithDouble: targetValue] forKey:@"value"];
 | ||
|                 [U3DAnalytics onTchErrorEvent:@"no_value" andRaw:json andOther:@""];
 | ||
|             } else {
 | ||
|                 if([_value doubleValue] < targetValue){
 | ||
|                     [dict setValue: [NSNumber numberWithDouble: targetValue] forKey:@"value"];
 | ||
|                     [U3DAnalytics onTchErrorEvent:@"value_error"
 | ||
|                                            andRaw:json andOther: [_value stringValue]];
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 上报 tch_error 事件
 | ||
| +(void) onTchErrorEvent:(NSString *) evtName andRaw: (NSString *)raw andOther: (NSString *) other{
 | ||
|     NSString *json = [NSString stringWithFormat:@"{\"event\":\"%@\", \"raw\":\"%@\", \"other\":\"%@\"}", evtName, raw, other];
 | ||
|     
 | ||
|     [GuruAnalytics logEvent:TchError
 | ||
|                  parameters:[U3DAnalytics buildDataWithJson:json andKey:evtName]];
 | ||
| }
 | ||
| 
 | ||
| // 对象判空
 | ||
| + (BOOL)isNullObject:(__kindof id) obj{
 | ||
|     if(!obj){
 | ||
|         return YES;
 | ||
|     }
 | ||
|     
 | ||
|     if(obj == NULL){
 | ||
|         return YES;
 | ||
|     }
 | ||
|     
 | ||
|     if([obj isEqual:[NSNull null]]){
 | ||
|         return YES;
 | ||
|     }
 | ||
|     
 | ||
|     return NO;
 | ||
| }
 | ||
| 
 | ||
| @end
 | ||
| 
 | ||
| //============================ UNITY PUBLIC API ============================
 | ||
| 
 | ||
| extern "C" {
 | ||
|  
 | ||
|     // 请求GDPR
 | ||
|     void unityInitAnalytics(const char *appId, const char *deviceInfo, bool isDebug)
 | ||
|     {
 | ||
| //        NSLog(@"--- [iOS] init Analytics libs");
 | ||
|         [GuruAnalytics initializeLibWithUploadPeriodInSecond:kUploadPeriodInSecond
 | ||
|                                                   batchLimit:kBatchLimit
 | ||
|                                          eventExpiredSeconds:kEventExpiredSeconds
 | ||
|                                            initializeTimeout:kInitializeTimeout
 | ||
|                                                   saasXAPPID:[U3DAnalytics charToString:appId]
 | ||
|                                              saasXDEVICEINFO:[U3DAnalytics charToString:deviceInfo]
 | ||
|                                                  loggerDebug:isDebug];
 | ||
|     }
 | ||
| 
 | ||
|     // 设置用户ID
 | ||
|     void unitySetUserID(const char *uid){
 | ||
|         [GuruAnalytics setUserID:[U3DAnalytics charToString:uid]];
 | ||
|     }
 | ||
| 
 | ||
|     // 设置用户ID
 | ||
|     void unitySetScreen(const char *screenName){
 | ||
|         [GuruAnalytics setScreen:[U3DAnalytics charToString:screenName]];
 | ||
|     }
 | ||
| 
 | ||
|     // 设置用户ADID
 | ||
|     void unitySetAdId(const char *adId){
 | ||
|         [GuruAnalytics setAdId:[U3DAnalytics charToString:adId]];
 | ||
|     }
 | ||
| 
 | ||
|     // 设置用户AdjustID
 | ||
|     void unitySetAdjustID(const char *adjustId){
 | ||
|         [GuruAnalytics setAdjustId:[U3DAnalytics charToString:adjustId]];
 | ||
|     }
 | ||
| 
 | ||
|     // 设置用户FirebaseID
 | ||
|     void unitySetFirebaseId(const char *firebaseId){
 | ||
|         [GuruAnalytics setFirebaseId:[U3DAnalytics charToString:firebaseId]];
 | ||
|     }
 | ||
| 
 | ||
|     // 设置用户设备ID
 | ||
|     void unitySetDeviceId(const char *did){
 | ||
|         [GuruAnalytics setDeviceId:[U3DAnalytics charToString:did]];
 | ||
|     }
 | ||
|     
 | ||
|     // 设置用户属性
 | ||
|     void unitySetUserProperty(const char *key, const char *value){
 | ||
|         [GuruAnalytics setUserProperty:[U3DAnalytics charToString:value]
 | ||
|                                forName:[U3DAnalytics charToString:key]];
 | ||
|     }
 | ||
|     
 | ||
|     // 上报事件
 | ||
|     void unityLogEvent(const char *key, const char *data){
 | ||
|         NSString *evtName = [U3DAnalytics charToString:key];
 | ||
|         NSString *json = [U3DAnalytics charToString:data];
 | ||
|         
 | ||
|         [GuruAnalytics logEvent: evtName
 | ||
|                      parameters:[U3DAnalytics buildDataWithJson:json andKey:evtName]]; // JSON转换
 | ||
|     }
 | ||
|     
 | ||
|     // 上报事件
 | ||
|     void unitySetTch02Value(const double value){
 | ||
|         [U3DAnalytics setTch02MaxValue:value];
 | ||
|     }
 | ||
| 
 | ||
|     // 打点事件成功率
 | ||
|     void unityReportEventRate(void){
 | ||
|         [GuruAnalytics debug_eventsStatistics:^(NSInteger uploadedEventsCount, NSInteger loggedEventsCount) {
 | ||
|         
 | ||
|             // 上报事件总量
 | ||
|             [GuruAnalytics setUserProperty:[NSString stringWithFormat:@"%ld", loggedEventsCount]
 | ||
|                                    forName:@"lgd"];
 | ||
|             // 上报成功数量
 | ||
|             [GuruAnalytics setUserProperty:[NSString stringWithFormat:@"%ld", uploadedEventsCount]
 | ||
|                                    forName:@"uld"];
 | ||
|         }];
 | ||
|     }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 |