init commit
						commit
						db327b4157
					
				|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 729cc47bf56d436ba4c20380ca1e5e59 | ||||||
|  | timeCreated: 1673860499 | ||||||
|  | @ -0,0 +1,35 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!--  | ||||||
|  | Sample Dependencies.xml: | ||||||
|  |     https://github.com/googlesamples/unity-jar-resolver/blob/master/sample/Assets/ExternalDependencyManager/Editor/SampleDependencies.xml | ||||||
|  | --> | ||||||
|  | <dependencies> | ||||||
|  |     <androidPackages> | ||||||
|  |         <androidPackage spec="androidx.core:core:1.7.0" /> | ||||||
|  | <!--        <androidPackage spec="androidx.appcompat:appcompat:1.5.1" />--> | ||||||
|  |         <androidPackage spec="androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" /> | ||||||
|  |         <androidPackage spec="androidx.work:work-runtime:2.7.1" /> | ||||||
|  |         <androidPackage spec="androidx.work:work-runtime-ktx:2.7.1" /> | ||||||
|  |         <androidPackage spec="androidx.work:work-rxjava2:2.7.1" /> | ||||||
|  |         <androidPackage spec="androidx.lifecycle:lifecycle-process:2.4.0" /> | ||||||
|  |         <androidPackage spec="com.jakewharton.timber:timber:4.7.1" /> | ||||||
|  |         <androidPackage spec="com.google.code.gson:gson:2.8.5" /> | ||||||
|  |         <androidPackage spec="androidx.room:room-runtime:2.4.3" /> | ||||||
|  |         <androidPackage spec="androidx.room:room-rxjava2:2.4.3" /> | ||||||
|  |         <androidPackage spec="com.squareup.retrofit2:retrofit:2.7.1" /> | ||||||
|  |         <androidPackage spec="com.squareup.retrofit2:converter-gson:2.7.1" /> | ||||||
|  |         <androidPackage spec="com.squareup.retrofit2:adapter-rxjava2:2.7.1" /> | ||||||
|  |         <androidPackage spec="com.squareup.okhttp3:okhttp:4.9.3" /> | ||||||
|  |          | ||||||
|  | <!--        <androidPackage spec="com.mapzen:on-the-road:0.8.1" />--> | ||||||
|  | <!--        <androidPackage spec="com.squareup.retrofit2:retrofit:2.7.1" />--> | ||||||
|  |     </androidPackages> | ||||||
|  |     <iosPods> | ||||||
|  |         <iosPod name="GuruAnalyticsLib" version="0.2.16" bitcodeEnabled="false"> | ||||||
|  |             <sources> | ||||||
|  |                 <source>git@github.com:castbox/GuruSpecs.git</source> | ||||||
|  |             </sources> | ||||||
|  |         </iosPod> | ||||||
|  |         <iosPod name="JJException" bitcodeEnabled="false" /> | ||||||
|  |     </iosPods> | ||||||
|  | </dependencies> | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: b9cafb1d82bb45598fdd566d9b8f6a80 | ||||||
|  | timeCreated: 1674110869 | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | -keep class com.guru.** { *; } | ||||||
|  | -keep class guru.core.** { *; } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: fb5e4cd53ce674f5ebbb1d5d865a0127 | ||||||
|  | TextScriptImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 9285dfb682d54e929bf0072a504e41b7 | ||||||
|  | timeCreated: 1690343284 | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | using System; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Guru; | ||||||
|  | using NUnit.Framework; | ||||||
|  | using UnityEngine; | ||||||
|  | 
 | ||||||
|  | public class GuruUnitTest | ||||||
|  | { | ||||||
|  |     private void TestInit(Action callback) | ||||||
|  |     { | ||||||
|  |         FirebaseUtil.InitFirebase(callback); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [Test] | ||||||
|  |     public void Test_Tch001() | ||||||
|  |     { | ||||||
|  |         TestInit(() => | ||||||
|  |         { | ||||||
|  |             double value = 0.0100000000899764; | ||||||
|  |             Analytics.Tch001ADRev(value); | ||||||
|  |             Analytics.Tch02ADRev(value); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: b6fe6b4805b4c40a1aea627baf6c976a | ||||||
|  | MonoImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   defaultReferences: [] | ||||||
|  |   executionOrder: 0 | ||||||
|  |   icon: {instanceID: 0} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: cd9f52a72bd884a9382ae92fc9ec2726 | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 127 KiB | 
|  | @ -0,0 +1,133 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 82a7793d183b045eeb9591cc4c15bd76 | ||||||
|  | TextureImporter: | ||||||
|  |   internalIDToNameTable: [] | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 12 | ||||||
|  |   mipmaps: | ||||||
|  |     mipMapMode: 0 | ||||||
|  |     enableMipMap: 1 | ||||||
|  |     sRGBTexture: 1 | ||||||
|  |     linearTexture: 0 | ||||||
|  |     fadeOut: 0 | ||||||
|  |     borderMipMap: 0 | ||||||
|  |     mipMapsPreserveCoverage: 0 | ||||||
|  |     alphaTestReferenceValue: 0.5 | ||||||
|  |     mipMapFadeDistanceStart: 1 | ||||||
|  |     mipMapFadeDistanceEnd: 3 | ||||||
|  |   bumpmap: | ||||||
|  |     convertToNormalMap: 0 | ||||||
|  |     externalNormalMap: 0 | ||||||
|  |     heightScale: 0.25 | ||||||
|  |     normalMapFilter: 0 | ||||||
|  |   isReadable: 0 | ||||||
|  |   streamingMipmaps: 0 | ||||||
|  |   streamingMipmapsPriority: 0 | ||||||
|  |   vTOnly: 0 | ||||||
|  |   grayScaleToAlpha: 0 | ||||||
|  |   generateCubemap: 6 | ||||||
|  |   cubemapConvolution: 0 | ||||||
|  |   seamlessCubemap: 0 | ||||||
|  |   textureFormat: 1 | ||||||
|  |   maxTextureSize: 2048 | ||||||
|  |   textureSettings: | ||||||
|  |     serializedVersion: 2 | ||||||
|  |     filterMode: 1 | ||||||
|  |     aniso: 1 | ||||||
|  |     mipBias: 0 | ||||||
|  |     wrapU: 0 | ||||||
|  |     wrapV: 0 | ||||||
|  |     wrapW: 0 | ||||||
|  |   nPOTScale: 1 | ||||||
|  |   lightmap: 0 | ||||||
|  |   compressionQuality: 50 | ||||||
|  |   spriteMode: 0 | ||||||
|  |   spriteExtrude: 1 | ||||||
|  |   spriteMeshType: 1 | ||||||
|  |   alignment: 0 | ||||||
|  |   spritePivot: {x: 0.5, y: 0.5} | ||||||
|  |   spritePixelsToUnits: 100 | ||||||
|  |   spriteBorder: {x: 0, y: 0, z: 0, w: 0} | ||||||
|  |   spriteGenerateFallbackPhysicsShape: 1 | ||||||
|  |   alphaUsage: 1 | ||||||
|  |   alphaIsTransparency: 0 | ||||||
|  |   spriteTessellationDetail: -1 | ||||||
|  |   textureType: 0 | ||||||
|  |   textureShape: 1 | ||||||
|  |   singleChannelComponent: 0 | ||||||
|  |   flipbookRows: 1 | ||||||
|  |   flipbookColumns: 1 | ||||||
|  |   maxTextureSizeSet: 0 | ||||||
|  |   compressionQualitySet: 0 | ||||||
|  |   textureFormatSet: 0 | ||||||
|  |   ignorePngGamma: 0 | ||||||
|  |   applyGammaDecoding: 0 | ||||||
|  |   cookieLightType: 0 | ||||||
|  |   platformSettings: | ||||||
|  |   - serializedVersion: 3 | ||||||
|  |     buildTarget: DefaultTexturePlatform | ||||||
|  |     maxTextureSize: 2048 | ||||||
|  |     resizeAlgorithm: 0 | ||||||
|  |     textureFormat: -1 | ||||||
|  |     textureCompression: 1 | ||||||
|  |     compressionQuality: 50 | ||||||
|  |     crunchedCompression: 0 | ||||||
|  |     allowsAlphaSplitting: 0 | ||||||
|  |     overridden: 0 | ||||||
|  |     androidETC2FallbackOverride: 0 | ||||||
|  |     forceMaximumCompressionQuality_BC6H_BC7: 0 | ||||||
|  |   - serializedVersion: 3 | ||||||
|  |     buildTarget: Standalone | ||||||
|  |     maxTextureSize: 2048 | ||||||
|  |     resizeAlgorithm: 0 | ||||||
|  |     textureFormat: -1 | ||||||
|  |     textureCompression: 1 | ||||||
|  |     compressionQuality: 50 | ||||||
|  |     crunchedCompression: 0 | ||||||
|  |     allowsAlphaSplitting: 0 | ||||||
|  |     overridden: 0 | ||||||
|  |     androidETC2FallbackOverride: 0 | ||||||
|  |     forceMaximumCompressionQuality_BC6H_BC7: 0 | ||||||
|  |   - serializedVersion: 3 | ||||||
|  |     buildTarget: iPhone | ||||||
|  |     maxTextureSize: 2048 | ||||||
|  |     resizeAlgorithm: 0 | ||||||
|  |     textureFormat: -1 | ||||||
|  |     textureCompression: 1 | ||||||
|  |     compressionQuality: 50 | ||||||
|  |     crunchedCompression: 0 | ||||||
|  |     allowsAlphaSplitting: 0 | ||||||
|  |     overridden: 0 | ||||||
|  |     androidETC2FallbackOverride: 0 | ||||||
|  |     forceMaximumCompressionQuality_BC6H_BC7: 0 | ||||||
|  |   - serializedVersion: 3 | ||||||
|  |     buildTarget: Android | ||||||
|  |     maxTextureSize: 2048 | ||||||
|  |     resizeAlgorithm: 0 | ||||||
|  |     textureFormat: -1 | ||||||
|  |     textureCompression: 1 | ||||||
|  |     compressionQuality: 50 | ||||||
|  |     crunchedCompression: 0 | ||||||
|  |     allowsAlphaSplitting: 0 | ||||||
|  |     overridden: 0 | ||||||
|  |     androidETC2FallbackOverride: 0 | ||||||
|  |     forceMaximumCompressionQuality_BC6H_BC7: 0 | ||||||
|  |   spriteSheet: | ||||||
|  |     serializedVersion: 2 | ||||||
|  |     sprites: [] | ||||||
|  |     outline: [] | ||||||
|  |     physicsShape: [] | ||||||
|  |     bones: [] | ||||||
|  |     spriteID:  | ||||||
|  |     internalID: 0 | ||||||
|  |     vertices: [] | ||||||
|  |     indices:  | ||||||
|  |     edges: [] | ||||||
|  |     weights: [] | ||||||
|  |     secondaryTextures: [] | ||||||
|  |   spritePackingTag:  | ||||||
|  |   pSDRemoveMatte: 0 | ||||||
|  |   pSDShowRemoveMatteOption: 0 | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: cbde866c1fe3a4961b2412feddfe68a3 | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 2b5e2e7c4d1ed49cfb4b27dcfe69ab5a | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: a336b814594434b4092d38e5ce76577a | ||||||
|  | PluginImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   iconMap: {} | ||||||
|  |   executionOrder: {} | ||||||
|  |   defineConstraints: [] | ||||||
|  |   isPreloaded: 0 | ||||||
|  |   isOverridable: 0 | ||||||
|  |   isExplicitlyReferenced: 0 | ||||||
|  |   validateReferences: 1 | ||||||
|  |   platformData: | ||||||
|  |   - first: | ||||||
|  |       Android: Android | ||||||
|  |     second: | ||||||
|  |       enabled: 1 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       Any:  | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       Editor: Editor | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: | ||||||
|  |         DefaultValueInitialized: true | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: c5a9f9e11213b4bb78856debe4c967ca | ||||||
|  | PluginImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   iconMap: {} | ||||||
|  |   executionOrder: {} | ||||||
|  |   defineConstraints: [] | ||||||
|  |   isPreloaded: 0 | ||||||
|  |   isOverridable: 0 | ||||||
|  |   isExplicitlyReferenced: 0 | ||||||
|  |   validateReferences: 1 | ||||||
|  |   platformData: | ||||||
|  |   - first: | ||||||
|  |       Android: Android | ||||||
|  |     second: | ||||||
|  |       enabled: 1 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       Any:  | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       Editor: Editor | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: | ||||||
|  |         DefaultValueInitialized: true | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 1f7f3e184bd7d457b9e678321a69ad1b | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | source 'https://github.com/CocoaPods/Specs.git' | ||||||
|  | source 'git@github.com:castbox/GuruSpecs.git' | ||||||
|  | 
 | ||||||
|  | platform :ios, '11.0' | ||||||
|  | 
 | ||||||
|  | target 'UnityFramework' do | ||||||
|  | 
 | ||||||
|  |   pod 'GuruAnalyticsLib', '~>0.2.2' | ||||||
|  | #  pod 'GuruAnalyticsLib', :git => 'git@github.com:castbox/GuruAnalytics_iOS.git', :branch => 'dev' | ||||||
|  | end | ||||||
|  | target 'Unity-iPhone' do | ||||||
|  | end | ||||||
|  | use_frameworks! | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 10035163694574b63b74cd99c7ee5c68 | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,294 @@ | ||||||
|  | // ============================================== | ||||||
|  | //  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"]; | ||||||
|  |         }]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 621002eb5acb547ec95af0d804cfb17f | ||||||
|  | PluginImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   iconMap: {} | ||||||
|  |   executionOrder: {} | ||||||
|  |   defineConstraints: [] | ||||||
|  |   isPreloaded: 0 | ||||||
|  |   isOverridable: 0 | ||||||
|  |   isExplicitlyReferenced: 0 | ||||||
|  |   validateReferences: 1 | ||||||
|  |   platformData: | ||||||
|  |   - first: | ||||||
|  |       Any:  | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       Editor: Editor | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: | ||||||
|  |         DefaultValueInitialized: true | ||||||
|  |   - first: | ||||||
|  |       iPhone: iOS | ||||||
|  |     second: | ||||||
|  |       enabled: 1 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       tvOS: tvOS | ||||||
|  |     second: | ||||||
|  |       enabled: 1 | ||||||
|  |       settings: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,70 @@ | ||||||
|  | // | ||||||
|  | //  JJException.m | ||||||
|  | //  UnityFramework | ||||||
|  | // | ||||||
|  | //  Created by Castbox on 2023/2/28. | ||||||
|  | // | ||||||
|  | 
 | ||||||
|  | #import <Foundation/Foundation.h> | ||||||
|  | #import <UIKit/UIKit.h> | ||||||
|  | #import "UnityAppController+UnityInterface.h" | ||||||
|  | #import <JJException/JJException.h> | ||||||
|  | #import <FirebaseCrashlytics/FirebaseCrashlytics.h> | ||||||
|  | 
 | ||||||
|  | @interface U3DException : NSObject<JJExceptionHandle> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @end | ||||||
|  | 
 | ||||||
|  | @implementation U3DException | ||||||
|  | 
 | ||||||
|  | static U3DException *_instance; | ||||||
|  | 
 | ||||||
|  | + (instancetype)sharedInstance { | ||||||
|  |     static dispatch_once_t oneToken; | ||||||
|  |     dispatch_once(&oneToken,^{ | ||||||
|  |         _instance = [[self alloc]init]; | ||||||
|  |     }); | ||||||
|  |     return _instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | + (instancetype)allocWithZone:(NSZone *)zone{ | ||||||
|  |     static dispatch_once_t onceToken; | ||||||
|  |     dispatch_once(&onceToken, ^{ | ||||||
|  |         _instance = [super allocWithZone:zone]; | ||||||
|  |     }); | ||||||
|  |     return _instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | - (void)start { | ||||||
|  |     [JJException configExceptionCategory:JJExceptionGuardUnrecognizedSelector]; | ||||||
|  |     [JJException startGuardException]; | ||||||
|  |     [JJException registerExceptionHandle:self]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #pragma mark - Exception Delegate | ||||||
|  | 
 | ||||||
|  | - (void)handleCrashException:(NSString*)exceptionMessage extraInfo:(NSDictionary*)info{ | ||||||
|  |     NSLog(@"handleCrashException: %@ info: %@", exceptionMessage, info); | ||||||
|  |     NSArray *messages = [exceptionMessage componentsSeparatedByString:@"\n"]; | ||||||
|  |     NSString *domain = @"[U3DException]-handler exception"; | ||||||
|  |     if (messages.count > 2) { | ||||||
|  | //        messages.objectat | ||||||
|  |         domain = [messages objectAtIndex:2]; | ||||||
|  |     } | ||||||
|  |     NSError *error = [[NSError alloc] initWithDomain:domain code:-1 userInfo:@{NSLocalizedDescriptionKey: exceptionMessage}]; | ||||||
|  |     [[FIRCrashlytics crashlytics] recordError:error]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @end | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | extern "C" { | ||||||
|  |     void unityInitException() { | ||||||
|  |         [[U3DException sharedInstance] start]; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     void unityTestUnrecognizedSelectorCrash() { | ||||||
|  |         [[U3DException sharedInstance] performSelector:NSSelectorFromString(@"testUnrecognizedSelectorCrash")]; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 66c93bfd67d2e46f887594e87fa16b39 | ||||||
|  | PluginImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   iconMap: {} | ||||||
|  |   executionOrder: {} | ||||||
|  |   defineConstraints: [] | ||||||
|  |   isPreloaded: 0 | ||||||
|  |   isOverridable: 0 | ||||||
|  |   isExplicitlyReferenced: 0 | ||||||
|  |   validateReferences: 1 | ||||||
|  |   platformData: | ||||||
|  |   - first: | ||||||
|  |       Any:  | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       Editor: Editor | ||||||
|  |     second: | ||||||
|  |       enabled: 0 | ||||||
|  |       settings: | ||||||
|  |         DefaultValueInitialized: true | ||||||
|  |   - first: | ||||||
|  |       iPhone: iOS | ||||||
|  |     second: | ||||||
|  |       enabled: 1 | ||||||
|  |       settings: {} | ||||||
|  |   - first: | ||||||
|  |       tvOS: tvOS | ||||||
|  |     second: | ||||||
|  |       enabled: 1 | ||||||
|  |       settings: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,252 @@ | ||||||
|  | # Guru Unity Analytics | ||||||
|  | 
 | ||||||
|  | GuruAnalyticsLib 的 Unity 插件库 | ||||||
|  | 
 | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | ## Change Logs | ||||||
|  | 
 | ||||||
|  | ### 1.8.4 | ||||||
|  | - 优化Android 端 Worker 调用逻辑, 重启 Worker 有助于让打点数据更准确 | ||||||
|  | 
 | ||||||
|  | ### 1.8.3 | ||||||
|  | - 修复 fg 打点上报时长不正确的问题 | ||||||
|  | 
 | ||||||
|  | ### 1.8.2 | ||||||
|  | - 修复参数类型转换的BUG, param数据转换为JSON对象 | ||||||
|  | 
 | ||||||
|  | ### 1.8.1 | ||||||
|  | - 修复自打点浮点参数精度问题 | ||||||
|  | - 添加太极020数值设置接口 | ||||||
|  | 
 | ||||||
|  | ### 1.7.5 | ||||||
|  | - 删除 `androidx.appcompat:appcompat` 库依赖 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | </br> | ||||||
|  | 
 | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | ## Document | ||||||
|  | 
 | ||||||
|  | - 项目整合插件后, **请一定要在各插件的初始化后上报各相关ID**: | ||||||
|  | 
 | ||||||
|  | - 相关接口如下 | ||||||
|  | 
 | ||||||
|  | - ### UID | ||||||
|  | 
 | ||||||
|  |   ```C# | ||||||
|  | 
 | ||||||
|  |     // ---- 需要等待中台初始化后上报:  | ||||||
|  |     // 上报中台返回的用户ID | ||||||
|  |     string uid = IPMConfig.IPM_UID  | ||||||
|  |     GuruAnalytics.SetUid(uid); | ||||||
|  | 
 | ||||||
|  |   ``` | ||||||
|  | 
 | ||||||
|  | - ### DeviceID | ||||||
|  |   ```C# | ||||||
|  |     // 上报设备ID | ||||||
|  |     string deviceId = IPMConfig.IPM_DEVICE_ID | ||||||
|  |     GuruAnalytics.SetDeviceId(DeviceID); | ||||||
|  | 
 | ||||||
|  |   ``` | ||||||
|  | 
 | ||||||
|  | - ### FirebaseID | ||||||
|  |   ```C# | ||||||
|  | 
 | ||||||
|  |     // ---- 需要Firebase Analytic 初始化后, 异步获取对应的ID: | ||||||
|  |     private static async void InitFirebaseAnalytics() | ||||||
|  |     { | ||||||
|  |         Debug.Log($"---[ANA] IPM UID: {IPMConfig.IPM_UID}"); | ||||||
|  |          | ||||||
|  |         var task = FirebaseAnalytics.GetAnalyticsInstanceIdAsync(); | ||||||
|  |         await task; | ||||||
|  |         if (task.IsCompleted) | ||||||
|  |         { | ||||||
|  |             var fid = task.Result; | ||||||
|  |             if (!string.IsNullOrEmpty(fid)) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"---[ANA] Firebase ID: {fid}"); | ||||||
|  |                 GuruAnalytics.SetFirebaseId(fid); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             Debug.LogError("---- Get Firebase Analytics Instance Fail"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   ``` | ||||||
|  | 
 | ||||||
|  | - ### AdjustID | ||||||
|  | 
 | ||||||
|  |     ```C# | ||||||
|  | 
 | ||||||
|  |     // ---- Adjust 启动后调用:  | ||||||
|  |     string adjustID = Adjust.getAdid(); | ||||||
|  |     GuruAnalytics.SetAdjustId(adjustID);     | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  | - ### AdID | ||||||
|  | 
 | ||||||
|  |     ```C# | ||||||
|  |     string adId = ""; | ||||||
|  |     Adjust.getGoogleAdId(id => | ||||||
|  |     { | ||||||
|  |         Debug.Log($"---- [ADJ] ADId: {id}"); | ||||||
|  |         adId = id; | ||||||
|  |         GuruAnalytics.SetAdId(id); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  | - 上报用户属性: | ||||||
|  | 
 | ||||||
|  |     ```C# | ||||||
|  | 
 | ||||||
|  |         string item_category = "main"; | ||||||
|  |         int level = 7; | ||||||
|  | 
 | ||||||
|  |         GuruAnalytics.SetUserProperty("item_category", item_category); | ||||||
|  |         GuruAnalytics.SetUserProperty("level", level.ToString()); | ||||||
|  | 
 | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  | - 上报视图名称 | ||||||
|  | 
 | ||||||
|  |     ```C# | ||||||
|  | 
 | ||||||
|  |         string screenName = "MainView"; | ||||||
|  |         GuruAnalytics.SetScreen(screenName); | ||||||
|  | 
 | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - 上报自定义打点: | ||||||
|  | 
 | ||||||
|  |     ```C# | ||||||
|  | 
 | ||||||
|  |         string eventName = "user_get_coin"; | ||||||
|  |         Dictionary<string, dynamic> data = new Dictionary<string, dynamic>() | ||||||
|  |         { | ||||||
|  |             { "level", 7 }, | ||||||
|  |             { "user_coin", 105L }, | ||||||
|  |             { "win_rate", 21.25f }, | ||||||
|  |             { "b_level", 7 }, | ||||||
|  |             { "result", "retry" } | ||||||
|  |         }; | ||||||
|  |         GuruAnalytics.LogEvent(eventName, data); | ||||||
|  | 
 | ||||||
|  |     ``` | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | </br> | ||||||
|  | 
 | ||||||
|  | ## 依赖台配置说明 | ||||||
|  | 
 | ||||||
|  | 本项目已开始使用 `ExternalDependencyManager` 简称 `EDM` 来解决各种库的依赖问题 | ||||||
|  | 
 | ||||||
|  | 详细配置可见: [Dependencies.xml](Editor/Dependencies.xml) | ||||||
|  | 
 | ||||||
|  | IOS 项目注意配置如下图: | ||||||
|  | 
 | ||||||
|  | --> 取消勾选 **Link frameworks statically** | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### Android 项目配置: | ||||||
|  | 
 | ||||||
|  | 于主菜单 `BuildSettings/PlayerSettings/PubishSettings:` | ||||||
|  | 
 | ||||||
|  | 开启如下选项: | ||||||
|  | 
 | ||||||
|  | - [x] Custom Main Gradle Template | ||||||
|  | - [x] Custom Properties Gradle Template | ||||||
|  | 
 | ||||||
|  | 之后会在项目的 `Plugins/Android`内生成对应的文件. | ||||||
|  | 
 | ||||||
|  | (A) 修改 `gradleTemplate.properties` | ||||||
|  | 
 | ||||||
|  | 添加一下内容支持 `AndroidX` | ||||||
|  | 
 | ||||||
|  | ```java | ||||||
|  | org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M | ||||||
|  | org.gradle.parallel=true | ||||||
|  | android.enableR8=false | ||||||
|  | unityStreamingAssets=.unity3d**STREAMING_ASSETS** | ||||||
|  | android.useAndroidX=true | ||||||
|  | android.enableJetifier=true | ||||||
|  | **ADDITIONAL_PROPERTIES** | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | (B) 修改 `mainTemplate.gradle` | ||||||
|  | 
 | ||||||
|  | 于 `dependency` 内添加如下依赖 (目前会自动添加, 无需手动添加) | ||||||
|  | 
 | ||||||
|  | ```java | ||||||
|  | 
 | ||||||
|  | dependencies { | ||||||
|  |     ... | ||||||
|  | 
 | ||||||
|  |     implementation 'androidx.core:core:1.7.0' | ||||||
|  |     compile 'com.mapzen:on-the-road:0.8.1' | ||||||
|  | 
 | ||||||
|  |     // basicDependencies | ||||||
|  |     implementation 'androidx.appcompat:appcompat:1.5.1' | ||||||
|  |     implementation 'com.jakewharton.timber:timber:4.7.1' | ||||||
|  |     implementation 'com.google.code.gson:gson:2.8.5' | ||||||
|  |     // roomDependencies | ||||||
|  |     implementation 'androidx.room:room-runtime:2.4.3' | ||||||
|  |     implementation 'androidx.room:room-rxjava2:2.4.3' | ||||||
|  |     // retrofitDependencies | ||||||
|  |     implementation 'com.squareup.retrofit2:retrofit:2.7.1' | ||||||
|  |     implementation 'com.squareup.retrofit2:converter-gson:2.7.1' | ||||||
|  |     implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1' | ||||||
|  |     // okhttpDependencies | ||||||
|  |     implementation 'androidx.work:work-runtime:2.7.1' | ||||||
|  |     implementation 'androidx.work:work-runtime-ktx:2.7.1' | ||||||
|  |     implementation 'androidx.work:work-rxjava2:2.7.1' | ||||||
|  |     // process | ||||||
|  |     implementation 'androidx.lifecycle:lifecycle-process:2.4.0' | ||||||
|  |     // okhttp3 | ||||||
|  |     implementation 'com.squareup.okhttp3:okhttp:4.9.3' | ||||||
|  |      | ||||||
|  |     ... | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 最低 `minTarget` 设置为 **21** | ||||||
|  | 
 | ||||||
|  | (D) 修改 `proguard-user.txt` 文件, 在最后追加此插件的相关代码 | ||||||
|  | 
 | ||||||
|  | 若项目使用了 ProGuard 压缩混淆, 需要修改此文件, 否则可能造成JAVA类无法被找到 | ||||||
|  | 
 | ||||||
|  | ```java | ||||||
|  | 
 | ||||||
|  | ... | ||||||
|  | 
 | ||||||
|  | -keep class com.guru.** { *; } | ||||||
|  | -keep class guru.core.** { *; } | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | </br> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## 示例项目 | ||||||
|  | 
 | ||||||
|  | - 示例项目位于 [~Sample](~Sample) 目录内. 详见 [CuruAnalyticsDemo.cs](~Sample/CuruAnalyticsDemo.cs) | ||||||
|  | - 示例借用了 BallSortPuzzle 的 `AppID` 和 `BundleID` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 8def6937882714f739e50c9b1e011967 | ||||||
|  | TextScriptImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 1892c569dc49c456f9ae1d99ea76e3b9 | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 30c092dbfbc6d4194b436c91ae7290b9 | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,247 @@ | ||||||
|  | using System; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Globalization; | ||||||
|  | using System.Text; | ||||||
|  | using Newtonsoft.Json; | ||||||
|  | using UnityEngine; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |      | ||||||
|  |     public class GuruAnalytics | ||||||
|  |     { | ||||||
|  |         // Plugin Version | ||||||
|  |         public const string Version = "1.8.4"; | ||||||
|  |          | ||||||
|  |         public static readonly string Tag = "[ANA]";  | ||||||
|  |         private static IAnalyticsAgent _agent; | ||||||
|  | 
 | ||||||
|  |         public static IAnalyticsAgent Agent | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_agent == null) | ||||||
|  |                 { | ||||||
|  |     #if UNITY_EDITOR | ||||||
|  |                     _agent = new AnalyticsAgentStub(); | ||||||
|  |     #elif UNITY_ANDROID | ||||||
|  |                     _agent = new AnalyticsAgentAndroid(); | ||||||
|  |     #elif UNITY_IOS | ||||||
|  |                     _agent = new AnalyticsAgentIOS(); | ||||||
|  |     #endif | ||||||
|  |                 } | ||||||
|  |                 return _agent; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static Dictionary<string, string> _userProperties; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 用户属性缓存字典 | ||||||
|  |         /// </summary> | ||||||
|  |         public static Dictionary<string, string> UserProperties | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_userProperties == null) | ||||||
|  |                 { | ||||||
|  |                     _userProperties = new Dictionary<string, string>(10); | ||||||
|  |                 } | ||||||
|  |                 return _userProperties; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region 公用接口 | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 初始化接口 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void Init(string appId, string deviceInfo, bool isDebug = false) | ||||||
|  |         { | ||||||
|  |             Agent?.Init(appId, deviceInfo, isDebug); | ||||||
|  | #if UNITY_IOS | ||||||
|  |             // AnalyticsAgentIOS.TestCrashEvent(); // 测试触发一下崩溃事件 | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置视图名称 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="screenName"></param> | ||||||
|  |         public static void SetScreen(string screenName) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty($"screen_name", screenName); | ||||||
|  |             Agent?.SetScreen(screenName); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置广告ID | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="id"></param> | ||||||
|  |         public static void SetAdId(string id) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty($"ad_id", id); | ||||||
|  |             Agent?.SetAdId(id); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置用户属性 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="key"></param> | ||||||
|  |         /// <param name="value"></param> | ||||||
|  |         public static void SetUserProperty(string key, string value) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty(key, value); // 添加用户属性 | ||||||
|  |             Agent?.SetUserProperty(key, value); | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置Firebase ID | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="id"></param> | ||||||
|  |         public static void SetFirebaseId(string id) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty($"firebase_id", id); | ||||||
|  |             Agent?.SetFirebaseId(id); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置Adjust ID | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="id"></param> | ||||||
|  |         public static void SetAdjustId(string id) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty($"adjust_id", id); | ||||||
|  |             Agent?.SetAdjustId(id); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置设备ID | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="deviceId"></param> | ||||||
|  |         public static void SetDeviceId(string deviceId) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty($"device_id", deviceId); | ||||||
|  |             Agent?.SetDeviceId(deviceId); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置用户ID | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="uid"></param> | ||||||
|  |         public static void SetUid(string uid) | ||||||
|  |         { | ||||||
|  |             CacheUserProperty($"uid", uid); | ||||||
|  |             Agent?.SetUid(uid); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 上报事件成功率 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void ReportEventSuccessRate() => Agent?.ReportEventSuccessRate(); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 上报打点事件 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="eventName">事件名称</param> | ||||||
|  |         /// <param name="data">INT类型的值</param> | ||||||
|  |         public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null) | ||||||
|  |         { | ||||||
|  |             string raw = ""; | ||||||
|  |             if (data != null && data.Count > 0) | ||||||
|  |             { | ||||||
|  |                 raw = BuildParamsJson(data); | ||||||
|  |             } | ||||||
|  |             Debug.Log($"{Tag} event:{eventName} | raw: {raw}"); | ||||||
|  |             Agent?.LogEvent(eventName, raw); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static string BuildParamsString(Dictionary<string, dynamic> data) | ||||||
|  |         { | ||||||
|  |             string raw = ""; | ||||||
|  |             List<string> strList = new List<string>(data.Count); | ||||||
|  |             foreach (var kvp in data) | ||||||
|  |             { | ||||||
|  |                 strList.Add(BuildStringValue(kvp)); | ||||||
|  |                 raw = string.Join(",", strList); | ||||||
|  |             } | ||||||
|  |             return raw; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static string BuildParamsJson(Dictionary<string, dynamic> data) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 //  强制转换加入国家设置 | ||||||
|  |                 return JsonConvert.SerializeObject(data, new JsonSerializerSettings() | ||||||
|  |                 { | ||||||
|  |                     Culture = new CultureInfo("en-US"), | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 Debug.LogError(e); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return ""; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 构建带有类型格式的Str值 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="kvp"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         private static string BuildStringValue(KeyValuePair<string, dynamic> kvp) | ||||||
|  |         { | ||||||
|  |             if (kvp.Value is int || kvp.Value is long) | ||||||
|  |             { | ||||||
|  |                 return $"{kvp.Key}:i{kvp.Value}"; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if (kvp.Value is double || kvp.Value is float) | ||||||
|  |             { | ||||||
|  |                 double dValue = (double)((object)kvp.Value); | ||||||
|  |                 return $"{kvp.Key}:d{dValue.ToString("F11", new CultureInfo("en-US"))}";  // 保留精度进行转换 | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return $"{kvp.Key}:s{kvp.Value}"; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置太极02值 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="value"></param> | ||||||
|  |         public static void SetTch02Value(double value) | ||||||
|  |         { | ||||||
|  |             Debug.Log($"{Tag} set tch_02_value:{value}"); | ||||||
|  |             Agent?.SetTch02Value(value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region iOS独有接口 | ||||||
|  | 
 | ||||||
|  | #if UNITY_IOS | ||||||
|  |         // 触发测试崩溃埋点 | ||||||
|  |         public static void TestCrash() => AnalyticsAgentIOS.TestCrashEvent(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region 用户属性 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 记录用户属性 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="key"></param> | ||||||
|  |         /// <param name="value"></param> | ||||||
|  |         private static void CacheUserProperty(string key, string value) | ||||||
|  |         { | ||||||
|  |             UserProperties[key] = value; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 09fd5c799d5d24931a3974af59d496a3 | ||||||
|  | MonoImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   defaultReferences: [] | ||||||
|  |   executionOrder: 0 | ||||||
|  |   icon: {instanceID: 0} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// 自打点代理接口 | ||||||
|  |     /// </summary> | ||||||
|  |     public interface IAnalyticsAgent | ||||||
|  |     { | ||||||
|  |         void Init(string appId, string deviceInfo, bool isDebug = false); | ||||||
|  |         void SetScreen(string screenName); | ||||||
|  |         void SetAdId(string id); | ||||||
|  |         void SetUserProperty(string key, string value); | ||||||
|  |         void SetFirebaseId(string id); | ||||||
|  |         void SetAdjustId(string id); | ||||||
|  |         void SetDeviceId(string deviceId); | ||||||
|  |         void SetUid(string uid); | ||||||
|  |         bool IsDebug { get; } | ||||||
|  |         void LogEvent(string eventName, string parameters); | ||||||
|  |         void ReportEventSuccessRate(); // 上报任务成功率 | ||||||
|  |         void SetTch02Value(double value); // 设置太极02数值 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 0541b7a79e6e44a5aa8ab5cc00218c9b | ||||||
|  | timeCreated: 1672388238 | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: e9a20f30f62248ac88252dc5958a338b | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,95 @@ | ||||||
|  | using System; | ||||||
|  | using UnityEngine; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     public class AnalyticsAgentAndroid: IAnalyticsAgent | ||||||
|  |     { | ||||||
|  |          | ||||||
|  | #if UNITY_ANDROID | ||||||
|  |          | ||||||
|  |         public static readonly string AnalyticsClassName = "com.guru.unity.analytics.Analytics"; | ||||||
|  |         private static AndroidJavaClass _classAnalytics; | ||||||
|  |         private static AndroidJavaClass ClassAnalytics => _classAnalytics ??= new AndroidJavaClass(AnalyticsClassName); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  |         private static bool _isDebug = false; | ||||||
|  |         public static bool UseWorker = true; | ||||||
|  |              | ||||||
|  |         #region 工具方法 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 调用静态方法 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="methodName"></param> | ||||||
|  |         /// <param name="args"></param> | ||||||
|  |         private static void CallStatic(string methodName, params object[] args) | ||||||
|  |         { | ||||||
|  | #if UNITY_ANDROID | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 if (ClassAnalytics != null) | ||||||
|  |                 { | ||||||
|  |                     ClassAnalytics.CallStatic(methodName, args); | ||||||
|  |                     if(_isDebug) Debug.Log($"{GuruAnalytics.Tag} Android call static :: {methodName}"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 Debug.LogError(e.Message); | ||||||
|  |             } | ||||||
|  | #endif     | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 调用静态方法 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="methodName"></param> | ||||||
|  |         /// <param name="args"></param> | ||||||
|  |         /// <typeparam name="T"></typeparam> | ||||||
|  |         private static T CallStatic<T>(string methodName, params object[] args) | ||||||
|  |         {  | ||||||
|  | #if UNITY_ANDROID | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 if (ClassAnalytics != null) | ||||||
|  |                 { | ||||||
|  |                     if(_isDebug) Debug.Log($"{GuruAnalytics.Tag} Android call static <{typeof(T).ToString()}> :: {methodName}"); | ||||||
|  |                     return ClassAnalytics.CallStatic<T>(methodName, args); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 Debug.LogError(e.Message); | ||||||
|  |             } | ||||||
|  | #endif        | ||||||
|  |             return default(T);   | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region 接口实现 | ||||||
|  |          | ||||||
|  |         public void Init(string appId, string deviceInfo, bool isDebug = false) | ||||||
|  |         { | ||||||
|  |             _isDebug = isDebug; | ||||||
|  |             string bundleId = Application.identifier; | ||||||
|  |             CallStatic("init", appId, deviceInfo, bundleId, UseWorker, isDebug); // 调用接口    | ||||||
|  |         } | ||||||
|  |         public void SetScreen(string screenName) => CallStatic("setScreen", screenName); | ||||||
|  |         public void SetAdId(string id) => CallStatic("setAdId", id); | ||||||
|  |         public void SetUserProperty(string key, string value) => CallStatic("setUserProperty", key, value); | ||||||
|  |         public void SetFirebaseId(string id) => CallStatic("setFirebaseId", id); | ||||||
|  |         public void SetAdjustId(string id) =>  CallStatic("setAdjustId", id); | ||||||
|  |         public void SetDeviceId(string deviceId) => CallStatic("setDeviceId", deviceId); | ||||||
|  |         public void SetUid(string uid) => CallStatic("setUid", uid); | ||||||
|  |         public bool IsDebug => CallStatic<bool>("isDebug"); | ||||||
|  |         public void LogEvent(string eventName, string parameters) => CallStatic("logEvent", eventName, parameters); | ||||||
|  |         public void ReportEventSuccessRate() => CallStatic("reportEventRate"); | ||||||
|  |         public void SetTch02Value(double value) => CallStatic("setTch02Value", value); | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 27181ab00e124c639b1f4468c535047c | ||||||
|  | timeCreated: 1672389052 | ||||||
|  | @ -0,0 +1,124 @@ | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     public class AnalyticsAgentIOS: IAnalyticsAgent | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         #region 属性定义 | ||||||
|  | 
 | ||||||
|  |         private const string K_INTERNAL = "__Internal"; | ||||||
|  |          | ||||||
|  | #if UNITY_IOS | ||||||
|  |         // ------------- U3DAnalytics.mm Interface ----------------- | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unityInitAnalytics(string appId, string deviceInfo, bool isDebug); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetUserID(string uid); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetScreen(string screenName); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetAdId(string adId); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetAdjustID(string adjustId); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetFirebaseId(string fid); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetDeviceId(string did); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetUserProperty(string key, string value); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unityLogEvent(string key, string data); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unityReportEventRate(); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unityInitException(); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unityTestUnrecognizedSelectorCrash(); | ||||||
|  |         [DllImport(K_INTERNAL)] private static extern void unitySetTch02Value(double value); | ||||||
|  | #endif | ||||||
|  |          | ||||||
|  |         private static bool _isDebug = false;     | ||||||
|  |              | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region 接口实现 | ||||||
|  | 
 | ||||||
|  |         public void Init(string appId, string deviceInfo, bool isDebug = false) | ||||||
|  |         { | ||||||
|  |             _isDebug = isDebug; | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unityInitAnalytics(appId, deviceInfo, isDebug);     | ||||||
|  |             unityInitException(); // 初始化报错守护进程 | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetScreen(string screenName) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetScreen(screenName); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetAdId(string id) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetAdId(id); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetUserProperty(string key, string value) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetUserProperty(key, value); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetFirebaseId(string fid) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetFirebaseId(fid); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetAdjustId(string id) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetAdjustID(id); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetDeviceId(string deviceId) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetDeviceId(deviceId); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetUid(string uid) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetUserID(uid); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool IsDebug => _isDebug; | ||||||
|  | 
 | ||||||
|  |         public void LogEvent(string eventName, string data) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unityLogEvent(eventName, data); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public void ReportEventSuccessRate() | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unityReportEventRate(); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public void SetTch02Value(double value) | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             unitySetTch02Value(value); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  |          | ||||||
|  | #if UNITY_IOS | ||||||
|  |         // iOS 测试用事件 | ||||||
|  |         public static void TestCrashEvent()=> unityTestUnrecognizedSelectorCrash(); | ||||||
|  | #endif | ||||||
|  |          | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 93f0211868c14c60aed081f928dc114e | ||||||
|  | timeCreated: 1672901309 | ||||||
|  | @ -0,0 +1,122 @@ | ||||||
|  | using System.Text; | ||||||
|  | using UnityEngine; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     public class AnalyticsAgentStub: IAnalyticsAgent | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         public static readonly string TAG = "[EDT]"; | ||||||
|  | 
 | ||||||
|  |         private bool _isShowLog = false; | ||||||
|  |         private bool _isDebug = false; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         public void Init(string appId, string deviceInfo, bool isDebug = false) | ||||||
|  |         { | ||||||
|  | #if UNITY_EDITOR | ||||||
|  |             _isShowLog = true; | ||||||
|  | #endif | ||||||
|  |             _isDebug = isDebug; | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} init with Debug: <color=orange>{isDebug}</color>  appId:{appId}    deviceInfo:{deviceInfo}"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetScreen(string screenName) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetScreen: <color=orange>{screenName}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetAdId(string id) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetAdId: <color=orange>{id}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetUserProperty(string key, string value) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetUserProperty: <color=orange>{key} : {value}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetFirebaseId(string id) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetFirebaseId: <color=orange>{id}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetAdjustId(string id) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetAdjustId: <color=orange>{id}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetDeviceId(string deviceId) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetDeviceId: <color=orange>{deviceId}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void SetUid(string uid) | ||||||
|  |         { | ||||||
|  |             if(_isShowLog)  | ||||||
|  |                 Debug.Log($"{TAG} SetUid: <color=orange>{uid}</color>"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool IsDebug => _isDebug; | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         public void LogEvent(string eventName, string parameters) | ||||||
|  |         { | ||||||
|  |             if (_isShowLog) | ||||||
|  |             { | ||||||
|  |                 var raw = parameters.Split(','); | ||||||
|  |                 if (raw.Length > 0) | ||||||
|  |                 { | ||||||
|  |                     StringBuilder sb = new StringBuilder(); | ||||||
|  |                     for (int i = 0; i < raw.Length; i++) | ||||||
|  |                     { | ||||||
|  |                         var ss = raw[i]; | ||||||
|  |                         if(string.IsNullOrEmpty(ss)) continue; | ||||||
|  |                          | ||||||
|  |                         var p = ss.Split(':'); | ||||||
|  |                         if (p.Length > 1) | ||||||
|  |                         { | ||||||
|  |                              | ||||||
|  |                             var key = p[0]; | ||||||
|  |                             var t = p[1].Substring(0, 1); | ||||||
|  |                             var v = p[1].Substring(1, p[1].Length - 1); | ||||||
|  | 
 | ||||||
|  |                              | ||||||
|  |                             // 字符串解析 | ||||||
|  |                             switch(t){ | ||||||
|  |                                 case "i": | ||||||
|  |                                     sb.Append($"<color=orange>{key} : [int]{v}</color>\n"); | ||||||
|  |                                     break; | ||||||
|  |                                 case "d": | ||||||
|  |                                     sb.Append($"<color=orange>{key} : [double]{v}</color>\n"); | ||||||
|  |                                     break; | ||||||
|  |                                 default: | ||||||
|  |                                     sb.Append($"<color=orange>{key} : [string]{v}</color>\n"); | ||||||
|  |                                     break; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|  |                     Debug.Log($"{TAG} LogEvent: event:<color=orange>{eventName}</color>  Properties:\n{sb.ToString()}"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public void ReportEventSuccessRate() | ||||||
|  |         { | ||||||
|  |             Debug.Log($"{TAG} Log Event Success Rate"); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public void SetTch02Value(double value) | ||||||
|  |         { | ||||||
|  |             Debug.Log($"{TAG} Tch02MaxValue: {value}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 8fd78c80a8d44637819c9803c1b71724 | ||||||
|  | timeCreated: 1672389623 | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | { | ||||||
|  |     "name": "com.guru.unity.analytics", | ||||||
|  |     "displayName": "Guru SDK", | ||||||
|  |     "version": "1.8.4", | ||||||
|  |     "description": "Guru Custom Analytics", | ||||||
|  |     "unity": "2020.3", | ||||||
|  |     "author":{ | ||||||
|  |         "name": "Guru Fungames Studio" | ||||||
|  |     }, | ||||||
|  |     "license": "MIT", | ||||||
|  |     "category": "Game,Tool,Development", | ||||||
|  |     "dependencies": { | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 249b5c6c7b433404ea44e9eb2bd35066 | ||||||
|  | TextScriptImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 82693d012b64748c8ac997389b0426a7 | ||||||
|  | folderAsset: yes | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,138 @@ | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using UnityEngine; | ||||||
|  | using UnityEngine.UI; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     public class CuruAnalyticsDemo: MonoBehaviour | ||||||
|  |     { | ||||||
|  |         [SerializeField] private bool _isDebug = true;  | ||||||
|  |         [SerializeField] private Button _btnInitSDK; | ||||||
|  |         [SerializeField] private Button _btnStatus; | ||||||
|  |         [SerializeField] private Button _btnUserProperties; | ||||||
|  |         [SerializeField] private Button _btnEvents; | ||||||
|  |         [SerializeField] private Button _btnEvents2; | ||||||
|  |         [SerializeField] private Button _btnReport; | ||||||
|  |         [SerializeField] private Button _btnTestCrash; | ||||||
|  | 
 | ||||||
|  |         // ----------- All Status IDs ----------- | ||||||
|  |         private static readonly string AdjustID = "e35b41522140fa2db9089ef3c78eb8f9"; | ||||||
|  |         private static readonly string FirebaseID = "b7ab5fc399a7bc8725c004943fa82837"; | ||||||
|  |         private static readonly string UID = "BS-YYYYF"; | ||||||
|  |         private static readonly string AdID = "dda3cc2b-5a5e-44cb-8a59-4a0b1b3780fd"; | ||||||
|  |         private static readonly string DeviceID = "e2fb3c5a4c36473648c989bd86a41153"; | ||||||
|  |         private static readonly string AppID = ""; | ||||||
|  |         private static readonly string DeviceInfo = ""; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         private static readonly string ScreenName = "MainMenu"; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |         private void Awake() | ||||||
|  |         { | ||||||
|  |             _btnInitSDK.onClick.AddListener(OnClickInit); | ||||||
|  |             _btnStatus.onClick.AddListener(OnClickStatus); | ||||||
|  |             _btnUserProperties.onClick.AddListener(OnClickUserProperties); | ||||||
|  |             _btnEvents.onClick.AddListener(OnClickEvents); | ||||||
|  |             _btnEvents2.onClick.AddListener(OnClickEvents2); | ||||||
|  |             _btnReport.onClick.AddListener(OnClickReport); | ||||||
|  |             _btnTestCrash.onClick.AddListener(OnClickTestCrash); | ||||||
|  | #if !UNITY_IOS | ||||||
|  |             _btnTestCrash.gameObject.SetActive(false); | ||||||
|  | #endif | ||||||
|  |              | ||||||
|  |              | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region Button Callbacks | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private void OnClickInit() | ||||||
|  |         { | ||||||
|  |             Debug.Log($"---- [DEMO] Call Analytics init"); | ||||||
|  |             GuruAnalytics.Init(AppID, DeviceInfo, _isDebug); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         private void OnClickStatus() | ||||||
|  |         { | ||||||
|  |             Debug.Log($"---- [DEMO] Report Stats IDs:  UID:{UID}  DeviceID:{DeviceID}  FirebaseID:{FirebaseID} AdID:{AdID}  AdjustID:{AdjustID}"); | ||||||
|  |             GuruAnalytics.SetUid(UID); | ||||||
|  |             GuruAnalytics.SetDeviceId(DeviceID); | ||||||
|  |             GuruAnalytics.SetFirebaseId(FirebaseID); | ||||||
|  |             GuruAnalytics.SetAdId(AdID); | ||||||
|  |             GuruAnalytics.SetAdjustId(AdjustID); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnClickUserProperties() | ||||||
|  |         { | ||||||
|  |             string item_category = "main"; | ||||||
|  |             int level = 7; | ||||||
|  |             Debug.Log($"---- [DEMO] Call SetUserProperty: item_category:{item_category}  level:{level}"); | ||||||
|  |             GuruAnalytics.SetUserProperty("item_category", item_category); | ||||||
|  |             GuruAnalytics.SetUserProperty("level", level.ToString()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnClickEvents() | ||||||
|  |         { | ||||||
|  |             Debug.Log($"---- [DEMO] Report Screen: {ScreenName}"); | ||||||
|  |             GuruAnalytics.SetScreen(ScreenName); | ||||||
|  | 
 | ||||||
|  |             string eventName = "user_get_coin"; | ||||||
|  |             Dictionary<string, dynamic> data = new Dictionary<string, dynamic>() | ||||||
|  |             { | ||||||
|  |                 { "level", 7 }, | ||||||
|  |                 { "user_coin", 105L }, | ||||||
|  |                 { "win_rate", 21.25f }, | ||||||
|  |                 { "b_level", 7 }, | ||||||
|  |                 { "result", "retry" } | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             string s = "---- Data ----\n"; | ||||||
|  |             foreach (var k in data.Keys) | ||||||
|  |             { | ||||||
|  |                 s += $"-- K:{k}  V:{data[k]}\n"; | ||||||
|  |             } | ||||||
|  |             Debug.Log(s);    | ||||||
|  | 
 | ||||||
|  |             Debug.Log($"---- [DEMO] Call LogEvent"); | ||||||
|  |             GuruAnalytics.LogEvent(eventName, data); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnClickEvents2() | ||||||
|  |         { | ||||||
|  |             string eventName = "user_data_loaded"; | ||||||
|  |             GuruAnalytics.LogEvent(eventName); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private void OnClickReport() | ||||||
|  |         { | ||||||
|  |             GuruAnalytics.ReportEventSuccessRate(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private void OnClickTestCrash() | ||||||
|  |         { | ||||||
|  | #if UNITY_IOS | ||||||
|  |             Debug.Log($"--> OnClickTestCrash"); | ||||||
|  |             GuruAnalytics.TestCrash(); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 8fde2a18f7d347408a6b869ee03e7de9 | ||||||
|  | timeCreated: 1672712830 | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: ea095a004daab4fc096aa297c21fca99 | ||||||
|  | DefaultImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
		Loading…
	
		Reference in New Issue
	
	 huyufei
						huyufei