init commit

main
huyufei 2023-12-15 15:35:30 +08:00
commit db327b4157
46 changed files with 3886 additions and 0 deletions

3
Editor.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 729cc47bf56d436ba4c20380ca1e5e59
timeCreated: 1673860499

35
Editor/Dependencies.xml Normal file
View File

@ -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>

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b9cafb1d82bb45598fdd566d9b8f6a80
timeCreated: 1674110869

2
Editor/Proguards.txt Normal file
View File

@ -0,0 +1,2 @@
-keep class com.guru.** { *; }
-keep class guru.core.** { *; }

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fb5e4cd53ce674f5ebbb1d5d865a0127
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

3
Editor/Tests.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9285dfb682d54e929bf0072a504e41b7
timeCreated: 1690343284

View File

@ -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);
});
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b6fe6b4805b4c40a1aea627baf6c976a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/imgs.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cd9f52a72bd884a9382ae92fc9ec2726
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Editor/imgs/sc01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

133
Editor/imgs/sc01.png.meta Normal file
View File

@ -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:

8
Plugins.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cbde866c1fe3a4961b2412feddfe68a3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Plugins/Android.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2b5e2e7c4d1ed49cfb4b27dcfe69ab5a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -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.

View File

@ -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:

8
Plugins/iOS.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1f7f3e184bd7d457b9e678321a69ad1b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

14
Plugins/iOS/Podfile Normal file
View File

@ -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!

7
Plugins/iOS/Podfile.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 10035163694574b63b74cd99c7ee5c68
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

294
Plugins/iOS/U3DAnalytics.mm Normal file
View File

@ -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"];
}];
}
}

View File

@ -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:

View File

@ -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")];
}
}

View File

@ -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:

252
README.md Normal file
View File

@ -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**
![](Editor/imgs/sc01.png)
### 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`

7
README.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8def6937882714f739e50c9b1e011967
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1892c569dc49c456f9ae1d99ea76e3b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/Script.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 30c092dbfbc6d4194b436c91ae7290b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09fd5c799d5d24931a3974af59d496a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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数值
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0541b7a79e6e44a5aa8ab5cc00218c9b
timeCreated: 1672388238

8
Runtime/Script/Impl.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e9a20f30f62248ac88252dc5958a338b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 27181ab00e124c639b1f4468c535047c
timeCreated: 1672389052

View File

@ -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
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 93f0211868c14c60aed081f928dc114e
timeCreated: 1672901309

View File

@ -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}");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8fd78c80a8d44637819c9803c1b71724
timeCreated: 1672389623

14
package.json Normal file
View File

@ -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": {
}
}

7
package.json.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 249b5c6c7b433404ea44e9eb2bd35066
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
~Sample.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 82693d012b64748c8ac997389b0426a7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8fde2a18f7d347408a6b869ee03e7de9
timeCreated: 1672712830

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ea095a004daab4fc096aa297c21fca99
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: