CrashSight鸿蒙相关提交
parent
b82464de8c
commit
e04dcfee8e
|
|
@ -707,6 +707,7 @@ internal class BatchBuild
|
|||
|
||||
public CrashSightConfig CrashSight_Android { get; set; }
|
||||
public CrashSightConfig CrashSight_iOS { get; set; }
|
||||
public CrashSightConfig CrashSight_Harmony{get; set;}
|
||||
public TalkingDataConfig TalkingData { get; set; }
|
||||
public ThinkingDataConfig ThinkingData { get; set; }
|
||||
}
|
||||
|
|
@ -897,6 +898,23 @@ internal class BatchBuild
|
|||
Debug.Log("CrashSight配置已保存:" + crashSightData.id + "|" + crashSightData.key);
|
||||
}
|
||||
|
||||
#if UNITY_OPENHARMONY
|
||||
// 处理CrashSight_Harmony配置
|
||||
if (config.CrashSight_Harmony != null &&
|
||||
EditorUserBuildSettings.activeBuildTarget == BuildTarget.OpenHarmony)
|
||||
{
|
||||
var crashSightData = new PhxhSDK.Data.CrashSightData
|
||||
{
|
||||
id = config.CrashSight_Harmony.Id,
|
||||
key = config.CrashSight_Harmony.Key
|
||||
};
|
||||
|
||||
var json = JsonUtility.ToJson(crashSightData);
|
||||
WriteEncryptedJsonResource("CrashSightData", json);
|
||||
Debug.Log("CrashSight配置已保存:" + crashSightData.id + "|" + crashSightData.key);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config.TalkingData != null)
|
||||
{
|
||||
var talkingDataInitTool = new TalkingDataInitTool
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ ConfigURL: "http://yhpxkqgzatnrmbws.kedrgame.com"
|
|||
AppAccessKey: "0SoE48O9sayjkG8J"
|
||||
AppKey: "uUi_UI1oMKWo0VOSN1zme17Z70-FlAv3Lcx2mNhoYe4="
|
||||
|
||||
# 崩溃监控配置(仅 Android)
|
||||
CrashSight_Android:
|
||||
id: "669a94ce69" # 崩溃上报的 App ID
|
||||
key: "d9412717-2416-4270-b8bc-f7a0805f988f" # 崩溃上报的 Key
|
||||
# 崩溃监控配置(仅鸿蒙)
|
||||
CrashSight_Harmony:
|
||||
id: "88625404e2" # 崩溃上报的 App ID
|
||||
key: "bff9d9be-bbd7-4fc1-9176-653281f8ff51" # 崩溃上报的 Key
|
||||
|
||||
# TalkingData初始化
|
||||
TalkingData:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
#if SDK_CRASHSIGHT
|
||||
using System;
|
||||
using PhxhSDK.Data;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Diagnostics;
|
||||
|
||||
namespace PhxhSDK
|
||||
{
|
||||
public class CrashSightSdkHelper : SdkHelper
|
||||
{
|
||||
// 设置上报的目标域名,请根据项目需求进行填写。(必填)
|
||||
private const string crashServerUrl_Android = "https://android.crashsight.qq.com/pb/async";
|
||||
// 设置上报所指向的APP ID, 并进行初始化。APPID可以在管理端更多->产品设置->产品信息中找到。
|
||||
// private const string appId_Android = "669a94ce69";
|
||||
|
||||
private const string crashServerUrl_iOS = "https://ios.crashsight.qq.com/pb/sync";
|
||||
// private const string appId_iOS = "6ff03772f9";
|
||||
|
||||
private const string crashServerUrl_Harmony = "harmony.crashsight.qq.com";
|
||||
|
||||
public override void EarlyInit()
|
||||
{
|
||||
// Debug开关,Debug模式下会打印更多便于问题定位的Log.
|
||||
var enableDebug = false;
|
||||
#if DEBUG
|
||||
enableDebug = true;
|
||||
#endif
|
||||
CrashSightAgent.ConfigDebugMode(enableDebug);
|
||||
|
||||
var uploadUrl = "";
|
||||
switch (Application.platform)
|
||||
{
|
||||
case RuntimePlatform.Android:
|
||||
uploadUrl = crashServerUrl_Android;
|
||||
break;
|
||||
case RuntimePlatform.IPhonePlayer:
|
||||
uploadUrl = crashServerUrl_iOS;
|
||||
break;
|
||||
#if UNITY_OPENHARMONY
|
||||
case RuntimePlatform.OpenHarmony:
|
||||
uploadUrl = crashServerUrl_Harmony;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
DebugUtil.LogError("CrashSightSdkHelper" + "Unsupported platform: " + Application.platform);
|
||||
break;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(uploadUrl))
|
||||
{
|
||||
CrashSightAgent.ConfigCrashServerUrl(uploadUrl);
|
||||
}
|
||||
|
||||
var appId = "";
|
||||
if (!EncryptedResourceLoader.TryLoadJson<CrashSightData>("CrashSightData", out var data))
|
||||
{
|
||||
DebugUtil.LogError("CrashSightSdkHelper", "CrashSightData resource load failed");
|
||||
return;
|
||||
}
|
||||
appId = data.id;
|
||||
if (!string.IsNullOrEmpty(appId))
|
||||
{
|
||||
CrashSightAgent.InitWithAppId(appId);
|
||||
DebugUtil.Log("CrashSightSdkHelper", "CrashSight appId: " + appId);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugUtil.LogError("CrashSightSdkHelper" + "CrashSight appId is empty");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void AfterLoginInit()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Release()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void TestCrashJava()
|
||||
{
|
||||
CrashSightAgent.TestJavaCrash();
|
||||
}
|
||||
|
||||
public void TestOcCrash()
|
||||
{
|
||||
CrashSightAgent.TestOcCrash();
|
||||
}
|
||||
|
||||
public void TestCrashException()
|
||||
{
|
||||
throw new Exception("测试模拟异常");
|
||||
}
|
||||
|
||||
public void TestCrash()
|
||||
{
|
||||
UnityEngine.Diagnostics.Utils.ForceCrash(ForcedCrashCategory.AccessViolation);
|
||||
}
|
||||
|
||||
public void TestNativeCrash()
|
||||
{
|
||||
CrashSightAgent.TestNativeCrash();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f7558a87675ed9b4d8ddf26c290df6d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"group": "CrashSight",
|
||||
"libs": [
|
||||
"libz.dylib",
|
||||
"libc++.dylib"
|
||||
],
|
||||
"frameworks": [
|
||||
"SystemConfiguration.framework",
|
||||
"Security.framework",
|
||||
"JavaScriptCore.framework",
|
||||
"MetricKit.framework:weak",
|
||||
"OSLog.framework:weak",
|
||||
"CFNetwork.framework"
|
||||
],
|
||||
"headerpaths": [],
|
||||
"files": [],
|
||||
"folders": [],
|
||||
"excludes": ["^.*.meta$", "^.*.mdown$", "^.*.pdf$"],
|
||||
"compiler_flags": [],
|
||||
"linker_flags": [
|
||||
"-ObjC"
|
||||
]
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This Google Mobile Ads plugin library manifest will get merged with your
|
||||
application's manifest, adding the necessary activity and permissions
|
||||
required for displaying ads.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.uqm.gcloud.crashsight">
|
||||
<uses-sdk android:targetSdkVersion="30" android:minSdkVersion="15"/>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
|
||||
</manifest>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
|||
# crashsight sdk
|
||||
-keep public class com.uqm.crashsight.** { *; }
|
||||
-dontwarn com.uqm.crashsight.core.**
|
||||
-keep class com.uqm.crashsight.core.** { *; }
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
target=android-26
|
||||
android.library=true
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { CrashSightMain} from 'crashsight';
|
||||
import { GetFromGlobalThis } from 'crashsight/../../src/main/ets/common/GlobalThisUtil'
|
||||
import { common, Context } from '@kit.AbilityKit';
|
||||
|
||||
export function RegisterCrashSightBridge() {
|
||||
let register: Record<string, Object> = {};
|
||||
register["CrashSightObj"] = new CrashSightClass();
|
||||
return register;
|
||||
}
|
||||
|
||||
|
||||
export class CrashSightClass {
|
||||
|
||||
initContext(): number {
|
||||
|
||||
let context = GetFromGlobalThis("context") as Context;
|
||||
CrashSightMain.getInstance().initContextInJS(context);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Mobile Utils Plugin
|
||||
Created by Patryk Stepniewski
|
||||
Copyright (c) 2014-2019 gameDNA Ltd. All Rights Reserved.
|
||||
-->
|
||||
<root xmlns:android="http://schemas.openharmony.com">
|
||||
|
||||
<addRequestPermissions>
|
||||
<insert>
|
||||
ohos.permission.GET_NETWORK_INFO
|
||||
ohos.permission.INTERNET
|
||||
ohos.permission.GET_WIFI_INFO
|
||||
</insert>
|
||||
</addRequestPermissions>
|
||||
|
||||
<resourceCopies>
|
||||
<log text="CrashSight prebuildCopies"/>
|
||||
<log text="prebuildCopies $S(PluginDir)/CrashSight.har"/>
|
||||
<log text="prebuildCopies $S(BuildDir)/entry/hars/CrashSight.har"/>
|
||||
<copyFile src="$S(PluginDir)/CrashSight.har" dst="$S(BuildDir)/entry/hars/CrashSight.har"/>
|
||||
</resourceCopies>
|
||||
<ProjectOHPackageJsonOverridesAddHarPackageNames>
|
||||
<insert>
|
||||
CrashSight
|
||||
</insert>
|
||||
</ProjectOHPackageJsonOverridesAddHarPackageNames>
|
||||
<entryAbilityImportAdditions>
|
||||
<insert>
|
||||
import { CrashSightMain } from "CrashSight";
|
||||
</insert>
|
||||
</entryAbilityImportAdditions>
|
||||
|
||||
<AkiJSBindImportAdditions>
|
||||
<insert>
|
||||
import {CrashSightClass} from '../entryability/EntryAbility'
|
||||
</insert>
|
||||
</AkiJSBindImportAdditions>
|
||||
|
||||
|
||||
<AkiJSBindMainThreadAdditions>
|
||||
<insert>
|
||||
nativeRender.JSBind.bindFunction("CrashSightClass.initContext", CrashSightClass.initContext);
|
||||
</insert>
|
||||
</AkiJSBindMainThreadAdditions>
|
||||
|
||||
|
||||
<entryAbilityExternalClassAdditions>
|
||||
<insert>
|
||||
export class CrashSightClass {
|
||||
|
||||
|
||||
static initContext() :number{
|
||||
let context = GlobalContext.loadGlobalThis(GlobalContextConstants.UE_ABILITY_CONTEXT) as Context;
|
||||
CrashSightMain.getInstance().initContextInJS(context);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
</insert>
|
||||
</entryAbilityExternalClassAdditions>
|
||||
</root>
|
||||
Binary file not shown.
BIN
Tool/sdk_packages/CrashSight/0.0.2/Assets/PhxhSDK/ThirdParty/CrashSight/Plugins/Win/CrashSight/X86_64/CrashSight64.dll (Stored with Git LFS)
vendored
Normal file
BIN
Tool/sdk_packages/CrashSight/0.0.2/Assets/PhxhSDK/ThirdParty/CrashSight/Plugins/Win/CrashSight/X86_64/CrashSight64.dll (Stored with Git LFS)
vendored
Normal file
Binary file not shown.
|
|
@ -0,0 +1,81 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf5ae746b5b544136adfc380164166ce
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux64: 0
|
||||
Exclude OSXUniversal: 0
|
||||
Exclude WebGL: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 0
|
||||
Exclude iOS: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
AddToEmbeddedBinaries: false
|
||||
CPU: AnyCPU
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dade0c46327444572be5b78f63f416be
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
Exclude iOS: 0
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
AddToEmbeddedBinaries: true
|
||||
CompileFlags:
|
||||
FrameworkDependencies: CoreTelephony;Security;
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
|
@ -0,0 +1,245 @@
|
|||
//
|
||||
// CrashSight.h
|
||||
//
|
||||
// Version: 4.3.8(1084)
|
||||
//
|
||||
// Copyright (c) 2017年
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "CrashSightConfig.h"
|
||||
#import "CrashSightLog.h"
|
||||
|
||||
#define GCLOUD_VERSION_CRASHSIGHT "GCLOUD_VERSION_CRASHSIGHT_4.3.8.1084.sgprod"
|
||||
|
||||
|
||||
|
||||
typedef NS_OPTIONS(uint32_t, CSExceptionReprotOption) {
|
||||
CSExceptionReprotOptionNone = 0,
|
||||
CSExceptionReprotOptionSystemLog = 1 << 0,
|
||||
CSExceptionReprotOptionCustomLog = 1 << 1,
|
||||
CSExceptionReprotOptionKV = 1 << 2,
|
||||
CSExceptionReprotOptionCallback = 1 << 3,
|
||||
CSExceptionReprotOptionDumpStack = 1 << 4,
|
||||
};
|
||||
|
||||
@interface CrashSight : NSObject
|
||||
|
||||
/**
|
||||
* 初始化CrashSight,使用默认CrashSightConfigs
|
||||
*
|
||||
* @param appId 注册CrashSight分配的应用唯一标识
|
||||
*/
|
||||
+ (void)startWithAppId:(NSString * CS_NULLABLE)appId;
|
||||
|
||||
/**
|
||||
* 使用指定配置初始化CrashSight
|
||||
*
|
||||
* @param appId 注册CrashSight分配的应用唯一标识
|
||||
* @param config 传入配置的 CrashSightConfig
|
||||
*/
|
||||
+ (void)startWithAppId:(NSString * CS_NULLABLE)appId
|
||||
config:(CrashSightConfig * CS_NULLABLE)config;
|
||||
|
||||
/**
|
||||
* 使用指定配置初始化CrashSight
|
||||
*
|
||||
* @param appId 注册CrashSight分配的应用唯一标识
|
||||
* @param development 是否开发设备
|
||||
* @param config 传入配置的 CrashSightConfig
|
||||
*/
|
||||
+ (void)startWithAppId:(NSString * CS_NULLABLE)appId
|
||||
developmentDevice:(BOOL)development
|
||||
config:(CrashSightConfig * CS_NULLABLE)config;
|
||||
|
||||
/**
|
||||
* 设置用户标识
|
||||
*
|
||||
* @param userId 用户标识
|
||||
*/
|
||||
+ (void)setUserIdentifier:(NSString *)userId;
|
||||
|
||||
/**
|
||||
* 更新版本信息
|
||||
*
|
||||
* @param version 应用版本信息
|
||||
*/
|
||||
+ (void)updateAppVersion:(NSString *)version;
|
||||
|
||||
/**
|
||||
* 设置关键数据,随崩溃信息上报
|
||||
*
|
||||
* @param value KEY
|
||||
* @param key VALUE
|
||||
*/
|
||||
+ (void)setUserValue:(NSString *)value
|
||||
forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* 获取USER ID
|
||||
*
|
||||
* @return USER ID
|
||||
*/
|
||||
+ (NSString *)crashSightUserIdentifier;
|
||||
|
||||
/**
|
||||
* 获取关键数据
|
||||
*
|
||||
* @return 关键数据
|
||||
*/
|
||||
+ (NSDictionary * CS_NULLABLE)allUserValues;
|
||||
|
||||
|
||||
+ (void)setUserSceneTag:(NSString *)userSceneTag isUpload:(bool)upload;
|
||||
|
||||
|
||||
+ (NSString *)currentUserSceneTag;
|
||||
|
||||
/**
|
||||
* 获取设备ID
|
||||
*
|
||||
* @return 设备ID
|
||||
*/
|
||||
+ (NSString *)crashSightDeviceId;
|
||||
|
||||
/**
|
||||
* 上报自定义Objective-C异常
|
||||
*
|
||||
* @param exception 异常信息
|
||||
*/
|
||||
+ (void)reportException:(NSException *)exception;
|
||||
|
||||
/**
|
||||
* 上报错误
|
||||
*
|
||||
* @param error 错误信息
|
||||
*/
|
||||
+ (void)reportError:(NSError *)error;
|
||||
|
||||
/**
|
||||
* @brief 上报自定义错误
|
||||
*
|
||||
* @param category 类型(Cocoa=3,CSharp=4,JS=5,Lua=6)
|
||||
* @param aName 名称
|
||||
* @param aReason 错误原因
|
||||
* @param aStackArray 堆栈
|
||||
* @param info 附加数据
|
||||
* @param terminate 上报后是否退出应用进程
|
||||
*/
|
||||
+ (void)reportExceptionWithCategory:(NSUInteger)category
|
||||
name:(NSString *)aName
|
||||
reason:(NSString *)aReason
|
||||
callStack:(NSArray *)aStackArray
|
||||
extraInfo:(NSDictionary *)info
|
||||
terminateApp:(BOOL)terminate
|
||||
dumpDataType:(int) dumpDataType
|
||||
errorAttachmentPath:(NSString *)errorAttachmentPath;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 上报自定义错误
|
||||
*
|
||||
* @param category 类型(Cocoa=3,CSharp=4,JS=5,Lua=6)
|
||||
* @param aName 名称
|
||||
* @param aReason 错误原因
|
||||
* @param aStackArray 堆栈
|
||||
* @param info 附加数据
|
||||
* @param terminate 上报后是否退出应用进程
|
||||
*/
|
||||
+ (void)reportExceptionWithCategory:(NSUInteger)category
|
||||
name:(NSString *)aName
|
||||
reason:(NSString *)aReason
|
||||
callStack:(NSArray *)aStackArray
|
||||
extraInfoJSONString:(NSString *)info
|
||||
terminateApp:(BOOL)terminate
|
||||
dumpDataType:(int) dumpDataType
|
||||
errorAttachmentPath:(NSString *)errorAttachmentPath;
|
||||
|
||||
|
||||
+ (void) reportLogInfo:(NSString *)messageType message:(NSString *)message;
|
||||
|
||||
|
||||
+ (void)reportJankWithName:(NSString *)name message:(NSString *)message stack:(NSArray *)stack extraInfo:(NSDictionary *)extraInfo option:(CSExceptionReprotOption)option attachmentPath:(nullable NSString *)attachmentPath;
|
||||
|
||||
/**
|
||||
* SDK 版本信息
|
||||
*
|
||||
* @return SDK版本号
|
||||
*/
|
||||
+ (NSString *)sdkVersion;
|
||||
|
||||
/**
|
||||
* APP 版本信息
|
||||
*
|
||||
* @return SDK版本号
|
||||
*/
|
||||
+ (NSString *)appVersion;
|
||||
|
||||
/**
|
||||
* App 是否发生了连续闪退
|
||||
* 如果 启动SDK 且 5秒内 闪退,且次数达到 3次 则判定为连续闪退
|
||||
*
|
||||
* @return 是否连续闪退
|
||||
*/
|
||||
+ (BOOL)isAppCrashedOnStartUpExceedTheLimit;
|
||||
|
||||
/**
|
||||
* 关闭crashSight监控
|
||||
*/
|
||||
+ (void)closeCrashReport;
|
||||
|
||||
/**
|
||||
* 再次注册CrashSight对Crash监听
|
||||
*/
|
||||
+ (void)reregisterCrashHandler;
|
||||
|
||||
/**
|
||||
* 设置上报URL,可在初始化CrashSight后动态设置
|
||||
*/
|
||||
+ (void)setServerUrl:(NSString *)url;
|
||||
|
||||
/**
|
||||
* 设置上报附件的绝对路径
|
||||
*/
|
||||
+ (void)setAttachmentPath:(NSString *)path;
|
||||
|
||||
+ (int)getCrashThreadId;
|
||||
|
||||
|
||||
+ (NSString *)crashSightSessionId;
|
||||
|
||||
+ (BOOL)isLastSessionCrash;
|
||||
|
||||
+ (NSString *)getLastSessionUserId;
|
||||
|
||||
+ (NSDictionary *)ccConifg;
|
||||
|
||||
+ (int)getExceptionType:(NSString *)name;
|
||||
|
||||
+ (void)setServerEnv:(NSString *)serverEnv;
|
||||
|
||||
+ (void)setEngineInfo:(NSString *)version buildConfig:(NSString *)buildConfig language:(NSString *)language locale:(NSString *)locale;
|
||||
|
||||
+ (void)enableDetailedPageTracing:(bool)enable;
|
||||
|
||||
+ (void)useSavedUserId:(bool)enable;
|
||||
|
||||
+ (void)reportStuckWithThreadIndex:(int)threadIndex
|
||||
maxChecks:(int)maxChecks
|
||||
checkInterval:(NSTimeInterval)checkInterval
|
||||
name:(NSString *)name
|
||||
message:(NSString *)message
|
||||
extraInfo:(NSString *)extraInfo
|
||||
dumpNativeType:(int)dumpNativeType
|
||||
attachPath:(NSString *)attachPath;
|
||||
|
||||
|
||||
|
||||
|
||||
// 必须在lua线程调用, 否则捕获lua堆栈时会崩溃
|
||||
+ (void)setLuaState:(nonnull void*)lua;
|
||||
|
||||
+ (void)setLuaFuncGetglobal:(nonnull void *)getglobal getfield:(nonnull void *)getfield pushstring:(nonnull void *)pushstring pushinteger:(nonnull void *)pushinteger pcallk:(nonnull void *)pcallk tolstring:(nonnull void *)tolstring settop:(nonnull void *)settop;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
//
|
||||
// CrashSightConfig.h
|
||||
// CrashSight
|
||||
//
|
||||
// Copyright (c) 2016年
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CS_UNAVAILABLE(x) __attribute__((unavailable(x)))
|
||||
|
||||
#if __has_feature(nullability)
|
||||
#define CS_NONNULL __nonnull
|
||||
#define CS_NULLABLE __nullable
|
||||
#define CS_START_NONNULL _Pragma("clang assume_nonnull begin")
|
||||
#define CS_END_NONNULL _Pragma("clang assume_nonnull end")
|
||||
#else
|
||||
#define CS_NONNULL
|
||||
#define CS_NULLABLE
|
||||
#define CS_START_NONNULL
|
||||
#define CS_END_NONNULL
|
||||
#endif
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "CrashSightLog.h"
|
||||
|
||||
#define CS_CALLBACK_FLAGS_LUA 0x1
|
||||
#define CS_CALLBACK_FLAGS_JS (0x1 << 1)
|
||||
#define CS_CALLBACK_FLAGS_CSHARP (0x1 << 2)
|
||||
#define CS_CALLBACK_FLAGS_CRASH (0x1 << 4)
|
||||
#define CS_CALLBACK_FLAGS_CUSTOM (0x1 << 5)
|
||||
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSCallbackType) {
|
||||
CSCallbackTypeNone = 0,
|
||||
CSCallbackTypeCrash = 2,
|
||||
CSCallbackTypeCShap = 3,
|
||||
CSCallbackTypeJS = 5,
|
||||
CSCallbackTypeLua = 6,
|
||||
CSCallbackTypeCustom = 8,
|
||||
CSCallbackTypeJank = 9,
|
||||
};
|
||||
typedef CSCallbackType CSExceptionType;
|
||||
|
||||
@protocol CrashSightDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
/**
|
||||
* 发生异常时回调
|
||||
*
|
||||
* @param exception 异常信息
|
||||
*
|
||||
* @return 返回需上报记录,随异常上报一起上报
|
||||
*/
|
||||
- (NSString * CS_NULLABLE)attachmentForException:(NSException * CS_NULLABLE)exception callbackType:(CSCallbackType)callbackType;
|
||||
|
||||
/**
|
||||
* 设置UQM的崩溃时触发回调的方法
|
||||
* @return 返回崩溃时需要上报的日志路径
|
||||
*/
|
||||
- (NSString * CS_NULLABLE)attachmentLogPathForExceptionType:(CSExceptionType)exceptionType;
|
||||
|
||||
/**
|
||||
* 设置UQM的崩溃时触发回调的方法
|
||||
* 通知日志上报结果
|
||||
*/
|
||||
- (void)attachmentLogUploadResultForExceptionType:(CSExceptionType)exceptionType result:(int) result;
|
||||
|
||||
|
||||
/**
|
||||
* 策略激活时回调
|
||||
*
|
||||
* @param tacticInfo
|
||||
*
|
||||
* @return app是否弹框展示
|
||||
*/
|
||||
- (BOOL) h5AlertForTactic:(NSDictionary *)tacticInfo;
|
||||
|
||||
@end
|
||||
|
||||
@interface CrashSightConfig : NSObject
|
||||
|
||||
/**
|
||||
* SDK Debug信息开关, 默认关闭
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL debugMode;
|
||||
|
||||
/**
|
||||
* 设置自定义渠道标识
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *channel;
|
||||
|
||||
/**
|
||||
* 设置自定义版本号
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *version;
|
||||
|
||||
/**
|
||||
* 设置自定义设备唯一标识
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *deviceIdentifier;
|
||||
|
||||
/**
|
||||
* 卡顿监控开关,默认关闭
|
||||
*/
|
||||
@property (nonatomic) BOOL blockMonitorEnable;
|
||||
|
||||
/**
|
||||
* 卡顿监控判断间隔,单位为秒
|
||||
*/
|
||||
@property (nonatomic) NSTimeInterval blockMonitorTimeout;
|
||||
|
||||
/**
|
||||
* 设置 App Groups Id (如有使用 CrashSight iOS Extension SDK,请设置该值)
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *applicationGroupIdentifier;
|
||||
|
||||
/**
|
||||
* 进程内还原开关,默认开启
|
||||
*/
|
||||
@property (nonatomic) BOOL symbolicateInProcessEnable;
|
||||
|
||||
/**
|
||||
* @deprecate
|
||||
* 已经改为云控控制,用户配置无效
|
||||
* 非正常退出事件记录开关,默认关闭
|
||||
*/
|
||||
@property (nonatomic) BOOL unexpectedTerminatingDetectionEnable;
|
||||
|
||||
/**
|
||||
* 页面信息记录开关,默认开启
|
||||
*/
|
||||
@property (nonatomic) BOOL viewControllerTrackingEnable;
|
||||
|
||||
/**
|
||||
* CrashSight Delegate
|
||||
*/
|
||||
@property (nonatomic, assign) id<CrashSightDelegate> delegate;
|
||||
|
||||
/**
|
||||
* 控制自定义日志上报,默认值为CrashSightLogLevelSilent,即关闭日志记录功能。
|
||||
* 如果设置为CrashSightLogLevelWarn,则在崩溃时会上报Warn、Error接口打印的日志
|
||||
*/
|
||||
@property (nonatomic, assign) CrashSightLogLevel reportLogLevel;
|
||||
|
||||
/**
|
||||
* 崩溃数据过滤器,如果崩溃堆栈的模块名包含过滤器中设置的关键字,则崩溃数据不会进行上报
|
||||
* 例如,过滤崩溃堆栈中包含搜狗输入法的数据,可以添加过滤器关键字SogouInputIPhone.dylib等
|
||||
*/
|
||||
@property (nonatomic, copy) NSArray *excludeModuleFilter;
|
||||
|
||||
/**
|
||||
* 控制台日志上报开关,默认开启
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL consolelogEnable;
|
||||
|
||||
/**
|
||||
* @deprecate
|
||||
* 崩溃退出超时,如果监听到崩溃后,App一直没有退出,则到达超时时间后会自动abort进程退出
|
||||
* 默认值 5s, 单位 秒
|
||||
* 当赋值为0时,则不会自动abort进程退出
|
||||
*/
|
||||
@property (nonatomic, assign) NSUInteger crashAbortTimeout;
|
||||
|
||||
/**
|
||||
* 设置自定义联网、crash上报域名
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *crashServerUrl;
|
||||
|
||||
|
||||
|
||||
/// CS_CALLBACK_FLAGS_LUA(0x1) | CS_CALLBACK_FLAGS_JA(0x1 << 1) | CS_CALLBACK_FLAGS_CSHARP(0x1 << 2) | CS_CALLBACK_FLAGS_CRASH(0x1 << 4), default: 0xFFFF
|
||||
@property (nonatomic, assign) uint32_t callbackFlags;
|
||||
|
||||
/**
|
||||
* 崩溃处理超时时间,单位秒
|
||||
* defalut:2秒, 小于等于0:不限制(20秒)
|
||||
*
|
||||
*/
|
||||
@property (nonatomic, assign) int crashProcessTimeout;
|
||||
|
||||
/**
|
||||
* 配置崩溃上报COS文件绝对路径,必须是文件路径,不支持文件夹路径, 文件最大10MB, 超过部分忽略。
|
||||
*
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *uploadUserAttchmentFilePath;
|
||||
|
||||
@property (nonatomic, copy) NSString *oomAttchmentFilePath;
|
||||
|
||||
|
||||
@property (nonatomic, assign) BOOL ignoreCallSigaltstackFunctionFailed;
|
||||
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
//
|
||||
// CrashSightLog.h
|
||||
// CrashSight
|
||||
//
|
||||
// Copyright (c) 2017年
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Log level for CrashSight Log
|
||||
typedef NS_ENUM(NSUInteger, CrashSightLogLevel) {
|
||||
CrashSightLogLevelSilent = 0,
|
||||
CrashSightLogLevelError = 1,
|
||||
CrashSightLogLevelWarn = 2,
|
||||
CrashSightLogLevelInfo = 3,
|
||||
CrashSightLogLevelDebug = 4,
|
||||
CrashSightLogLevelVerbose = 5,
|
||||
};
|
||||
#pragma mark -
|
||||
|
||||
OBJC_EXTERN void CSLog(CrashSightLogLevel level, NSString *format, ...) NS_FORMAT_FUNCTION(2, 3);
|
||||
|
||||
OBJC_EXTERN void CSLogv(CrashSightLogLevel level, NSString *format, va_list args) NS_FORMAT_FUNCTION(2, 0);
|
||||
|
||||
#pragma mark -
|
||||
#define CRASHSIGHT_LOG_MACRO(_level, fmt, ...) [CrashSightLog level:_level tag:nil log:fmt, ##__VA_ARGS__]
|
||||
|
||||
#define CSLogError(fmt, ...) CRASHSIGHT_LOG_MACRO(CrashSightLogLevelError, fmt, ##__VA_ARGS__)
|
||||
#define CSLogWarn(fmt, ...) CRASHSIGHT_LOG_MACRO(CrashSightLogLevelWarn, fmt, ##__VA_ARGS__)
|
||||
#define CSLogInfo(fmt, ...) CRASHSIGHT_LOG_MACRO(CrashSightLogLevelInfo, fmt, ##__VA_ARGS__)
|
||||
#define CSLogDebug(fmt, ...) CRASHSIGHT_LOG_MACRO(CrashSightLogLevelDebug, fmt, ##__VA_ARGS__)
|
||||
#define CSLogVerbose(fmt, ...) CRASHSIGHT_LOG_MACRO(CrashSightLogLevelVerbose, fmt, ##__VA_ARGS__)
|
||||
|
||||
#pragma mark - Interface
|
||||
@interface CrashSightLog : NSObject
|
||||
|
||||
/**
|
||||
* @brief 初始化日志模块
|
||||
*
|
||||
* @param level 设置默认日志级别,默认CSLogLevelSilent
|
||||
*
|
||||
* @param printConsole 是否打印到控制台,默认NO
|
||||
*/
|
||||
+ (void)initLogger:(CrashSightLogLevel) level consolePrint:(BOOL)printConsole;
|
||||
|
||||
/**
|
||||
* @brief 打印CSLogLevelInfo日志
|
||||
*
|
||||
* @param format 日志内容 总日志大小限制为:字符串长度30k,条数200
|
||||
*/
|
||||
+ (void)log:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2);
|
||||
|
||||
/**
|
||||
* @brief 打印日志
|
||||
*
|
||||
* @param level 日志级别
|
||||
* @param message 日志内容 总日志大小限制为:字符串长度30k,条数200
|
||||
*/
|
||||
+ (void)level:(CrashSightLogLevel) level logs:(NSString *)message;
|
||||
|
||||
/**
|
||||
* @brief 打印日志
|
||||
*
|
||||
* @param level 日志级别
|
||||
* @param format 日志内容 总日志大小限制为:字符串长度30k,条数200
|
||||
*/
|
||||
+ (void)level:(CrashSightLogLevel) level log:(NSString *)format, ... NS_FORMAT_FUNCTION(2, 3);
|
||||
|
||||
/**
|
||||
* @brief 打印日志
|
||||
*
|
||||
* @param level 日志级别
|
||||
* @param tag 日志模块分类
|
||||
* @param format 日志内容 总日志大小限制为:字符串长度30k,条数200
|
||||
*/
|
||||
+ (void)level:(CrashSightLogLevel) level tag:(NSString *) tag log:(NSString *)format, ... NS_FORMAT_FUNCTION(3, 4);
|
||||
|
||||
@end
|
||||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
framework module CrashSight {
|
||||
umbrella header "CrashSight.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypePerformanceData</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeCrashData</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeDeviceID</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeUserID</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>E174.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 865fe01356f9247b7878748577677c77
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
Exclude iOS: 0
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
AddToEmbeddedBinaries: true
|
||||
CompileFlags:
|
||||
FrameworkDependencies: Security;
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Created by joyfyzhang on 2021/10/18.
|
||||
//
|
||||
|
||||
#ifndef ANDROID_UQMUNITYBRIDGE_H
|
||||
#define ANDROID_UQMUNITYBRIDGE_H
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "UQMDefine.h"
|
||||
#include "UQM.h"
|
||||
#include "UQMUtils.h"
|
||||
#include "CSLogger.h"
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CrashSightCore/CrashSightCore.h>
|
||||
#endif
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
typedef char* (*UQMRetJsonCallback)(int methodId, int callbackType, int logUploadResult);
|
||||
|
||||
class UQMUnityBridge {
|
||||
public:
|
||||
static UQMRetJsonCallback SendToUnity;
|
||||
static void SetBridge(UQMRetJsonCallback bridge);
|
||||
static char *pInvokeHandleCallback(int methodId, int callbackType, int logUploadResult = 0) {
|
||||
if (UQMUnityBridge::SendToUnity == NULL) {
|
||||
UQM_LOG_DEBUG("No callback for unity, please do UQM.Init(); first !");
|
||||
return NULL;
|
||||
} else {
|
||||
return UQMUnityBridge::SendToUnity(methodId, callbackType, logUploadResult);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void UQM_EXPORT cs_setUnityCallback(UQMRetJsonCallback bridge);
|
||||
int UQM_EXPORT cs_unityForceCrash();
|
||||
int UQM_EXPORT cs_unityCrashCallback();
|
||||
int UQM_EXPORT cs_unityCrashLogCallback();
|
||||
int UQM_EXPORT cs_unregisterUnityCrashCallback();
|
||||
}
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif //ANDROID_UQMUNITYBRIDGE_H
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
//
|
||||
// Created by joyfyzhang on 2021/10/19.
|
||||
//
|
||||
|
||||
#ifndef ANDROID_UQMUNITYEXTRA_H
|
||||
#define ANDROID_UQMUNITYEXTRA_H
|
||||
|
||||
#include "UQMUnityBridge.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
///----- UQMCrash
|
||||
void UQM_EXPORT cs_configCallbackTypeAdapter(int32_t callbackType);
|
||||
|
||||
void UQM_EXPORT cs_configGameTypeAdapter(int gameType);
|
||||
|
||||
void UQM_EXPORT cs_configAutoReportLogLevelAdapter(int level);
|
||||
|
||||
void UQM_EXPORT cs_configDefaultAdapter(const char *channel, const char *version, const char *user, int64_t delay);
|
||||
|
||||
void UQM_EXPORT cs_configCrashServerUrlAdapter(const char *serverUrl);
|
||||
|
||||
void UQM_EXPORT cs_configDebugModeAdapter(bool enable);
|
||||
|
||||
void UQM_EXPORT cs_setDeviceIdAdapter(const char *deviceId);
|
||||
|
||||
/**
|
||||
* 设置业务的deviceId,仅用于页面搜索,不影响后台统计
|
||||
* @param deviceId
|
||||
*/
|
||||
void UQM_EXPORT cs_setCustomizedDeviceIDAdapter(const char *deviceId);
|
||||
|
||||
const char* UQM_EXPORT cs_getSDKDefinedDeviceIDAdapter();
|
||||
|
||||
void UQM_EXPORT cs_setCustomizedMatchIDAdapter(const char *matchId);
|
||||
|
||||
const char* UQM_EXPORT cs_getSDKSessionIDAdapter();
|
||||
|
||||
const char* UQM_EXPORT cs_getCrashUuidAdapter();
|
||||
|
||||
void UQM_EXPORT cs_setDeviceModelAdapter(const char *deviceModel);
|
||||
|
||||
void UQM_EXPORT cs_setCallbackMsgAdapter(const char *msg);
|
||||
|
||||
void UQM_EXPORT cs_initWithAppIdAdapter(const char *appId, bool forceOnUiThread);
|
||||
|
||||
void UQM_EXPORT cs_logRecordAdapter(int level, const char *message);
|
||||
|
||||
void UQM_EXPORT cs_addSceneDataAdapter(const char *key, const char *value);
|
||||
|
||||
void UQM_EXPORT cs_reportExceptionAdapter(int type, const char *exceptionName, const char *exceptionMsg,
|
||||
const char *exceptionStack, const char *extras, const char *paramsJson,
|
||||
bool quitProgram, int dumpNativeType, const char* errorAttachmentPath);
|
||||
|
||||
void UQM_EXPORT cs_setUserIdAdapter(const char *userId);
|
||||
|
||||
void UQM_EXPORT cs_setSceneAdapter(const char *sceneId, bool upload);
|
||||
|
||||
void UQM_EXPORT cs_setLogPathAdapter(const char *logPath);
|
||||
|
||||
void UQM_EXPORT cs_reRegistAllMonitorsAdapter();
|
||||
|
||||
void UQM_EXPORT cs_closeAllMonitorsAdapter();
|
||||
|
||||
void UQM_EXPORT cs_setAppVersionAdapter(const char *appVersion);
|
||||
|
||||
void UQM_EXPORT cs_crashObserverAdapter();
|
||||
|
||||
void UQM_EXPORT cs_unregisterCrashObserverAdapter();
|
||||
|
||||
void UQM_EXPORT cs_crashLogObserverAdapter();
|
||||
|
||||
void UQM_EXPORT cs_reportLogInfo(const char *msgType, const char *msg);
|
||||
|
||||
// test api
|
||||
void UQM_EXPORT cs_testOomCrashAdapter();
|
||||
|
||||
void UQM_EXPORT cs_testJavaCrashAdapter();
|
||||
|
||||
void UQM_EXPORT cs_testOcCrashAdapter();
|
||||
|
||||
void UQM_EXPORT cs_testNativeCrashAdapter();
|
||||
|
||||
void UQM_EXPORT cs_testANRAdapter();
|
||||
|
||||
void UQM_EXPORT cs_setCatchMultiSignal(bool enable);
|
||||
|
||||
void UQM_EXPORT cs_setUnwindExtraStack(bool enable);
|
||||
|
||||
long UQM_EXPORT cs_getCrashThreadId();
|
||||
|
||||
void UQM_EXPORT cs_setLogcatBufferSize(int size);
|
||||
|
||||
void UQM_EXPORT cs_startDumpRoutine(int dumpMode, int startTimeMode, long startTime, long dumpInterval,
|
||||
int dumpTimes, bool saveLocal, const char *savePath);
|
||||
|
||||
void UQM_EXPORT cs_startMonitorFdCount(int interval, int limit, int dumpType);
|
||||
|
||||
int UQM_EXPORT cs_getExceptionType(const char *name);
|
||||
|
||||
void UQM_EXPORT cs_testUseAfterFreeAdapter();
|
||||
|
||||
void UQM_EXPORT cs_setEnableGetPackageInfo(bool enable);
|
||||
|
||||
void UQM_EXPORT cs_setServerEnv(const char *serverEnv);
|
||||
|
||||
void UQM_EXPORT cs_setEngineInfo(const char *version, const char *buildConfig, const char *language, const char *locale);
|
||||
|
||||
void UQM_EXPORT cs_setGpuInfo(const char *version, const char *vendor, const char *renderer);
|
||||
|
||||
void UQM_EXPORT cs_enableDetailedPageTracing(bool enable);
|
||||
|
||||
void UQM_EXPORT cs_useSavedUserId(bool enable);
|
||||
|
||||
bool UQM_EXPORT cs_isLastSessionCrash();
|
||||
|
||||
const char* UQM_EXPORT cs_getLastSessionUserId();
|
||||
|
||||
bool UQM_EXPORT cs_checkFdCount(int limit, int dumpType, bool upload);
|
||||
|
||||
void UQM_EXPORT cs_setOomLogPath(const char *logPath);
|
||||
|
||||
void UQM_EXPORT cs_reportJank(int type, const char* exceptionName,
|
||||
const char* exceptionMsg, const char* exceptionStack,
|
||||
const char* extInfoJsonStr, int reportInfoOption, const char* jankAttachmentPath);
|
||||
|
||||
void UQM_EXPORT cs_processEngineAnr(int type);
|
||||
|
||||
void UQM_EXPORT cs_setEngineMainThread();
|
||||
|
||||
void UQM_EXPORT cs_reportStuck(int threadId, int maxChecks, int checkInterval,
|
||||
const char *name, const char *message, const char *extraInfo,
|
||||
int dumpNativeType, const char *attachPath);
|
||||
|
||||
|
||||
#if __APPLE__
|
||||
bool cs_showRatingAlertAdapter();
|
||||
void cs_showAppStoreProductViewAdapter(const char* appid);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //ANDROID_UQMUNITYEXTRA_H
|
||||
Binary file not shown.
|
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 19fc057f016ee4b3495e1f3f53003a19
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
Exclude iOS: 0
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
AddToEmbeddedBinaries: true
|
||||
CompileFlags:
|
||||
FrameworkDependencies: Security;
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef CSLogger_hpp
|
||||
#define CSLogger_hpp
|
||||
|
||||
#include "UQMMacros.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef CS_LOG_TAG
|
||||
#define CS_LOG_TAG "[CrashSightPlugin-Native]"
|
||||
#endif
|
||||
|
||||
// your convenient logger macro
|
||||
#define CSLoggerDebug(fmt, ...) CSLogger::log(CSLoggerLevel::CSLoggerLevelDebug, CS_LOG_TAG, fmt, ##__VA_ARGS__);
|
||||
#define UQM_LOG_DEBUG(fmt, ...) CSLogger::log(CSLoggerLevel::CSLoggerLevelDebug, CS_LOG_TAG, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define CSLoggerInfo(fmt, ...) CSLogger::log(CSLoggerLevel::CSLoggerLevelInfo, CS_LOG_TAG, fmt, ##__VA_ARGS__);
|
||||
#define CSLoggerWarn(fmt, ...) CSLogger::log(CSLoggerLevel::CSLoggerLevelWarn, CS_LOG_TAG, fmt, ##__VA_ARGS__);
|
||||
#define CSLoggerError(fmt, ...) CSLogger::log(CSLoggerLevel::CSLoggerLevelError, CS_LOG_TAG, fmt, ##__VA_ARGS__);
|
||||
#define UQM_LOG_ERROR(fmt, ...) CSLogger::log(CSLoggerLevel::CSLoggerLevelError, CS_LOG_TAG, fmt, ##__VA_ARGS__)
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CSLoggerLevelDebug = 0,
|
||||
CSLoggerLevelInfo,
|
||||
CSLoggerLevelWarn,
|
||||
CSLoggerLevelError,
|
||||
CSLoggerLevelSilent
|
||||
} CSLoggerLevel;
|
||||
|
||||
class UQM_EXPORT CSLogger
|
||||
{
|
||||
private:
|
||||
static CSLoggerLevel _loggerLevel;
|
||||
|
||||
public:
|
||||
static void setLoggerLevel(CSLoggerLevel loggerLevel);
|
||||
|
||||
static void log(CSLoggerLevel loggerLevel, const char *tag, const char *fmt, ...);
|
||||
|
||||
static void logv(CSLoggerLevel loggerLevel, const char *tag, const char *fmt, va_list args);
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* CSLogger_hpp */
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// Created by joyfyzhang on 2021/6/13.
|
||||
//
|
||||
|
||||
#ifndef UQM_CRASH_INTERFACE_H
|
||||
#define UQM_CRASH_INTERFACE_H
|
||||
|
||||
#include "UQMMacros.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 初始化函数
|
||||
* @param app_id CrashSight平台注册的AppID.
|
||||
* @param unexpected_terminating_detection_enable iOS异常退出检测,Android无效
|
||||
* @param debug_mode 是否开启调试模式,线上建议关闭
|
||||
* @param server_url 崩溃上报地址
|
||||
*/
|
||||
void UQM_EXPORT cs_init(const char* app_id, bool unexpected_terminating_detection_enable, bool debug_mode, const char* server_url);
|
||||
|
||||
|
||||
/**
|
||||
* 打印日志
|
||||
* @param level 日志级别 0-silent, 1-error, 2-warning, 3-info, 4-debug, 5-verbose
|
||||
* @param tag 日志标签
|
||||
* @param log 日志内容
|
||||
*/
|
||||
void UQM_EXPORT cs_log_info(int level, const char* tag, const char* log);
|
||||
|
||||
/**
|
||||
* 添加用户数据,崩溃时上报
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
void UQM_EXPORT cs_set_user_value(const char* key, const char* value);
|
||||
|
||||
/**
|
||||
* 设置用户ID
|
||||
* @param user_id 用户ID
|
||||
*/
|
||||
void UQM_EXPORT cs_set_user_id(const char* user_id);
|
||||
|
||||
/**
|
||||
* 上报捕获到的异常
|
||||
* @param type 异常类型
|
||||
* @param exception_name 异常名
|
||||
* @param exception_msg 异常消息
|
||||
* @param exception_stack 异常堆栈
|
||||
*/
|
||||
void UQM_EXPORT cs_report_exception(int type, const char* exception_name, const char* exception_msg, const char* exception_stack, bool is_dump_nativeStack= false);
|
||||
|
||||
|
||||
/**
|
||||
* 测试崩溃
|
||||
*/
|
||||
void UQM_EXPORT cs_trigger_crash();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //UQM_CRASH_INTERFACE_H
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// CrashSightCore.h
|
||||
// CrashSightCore
|
||||
//
|
||||
// Created by 张飞阳 on 2021/6/17.
|
||||
// Copyright © 2021 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#import <CrashSightCore/UQMRename.h>
|
||||
#import <CrashSightCore/UQMMacros.h>
|
||||
#import <CrashSightCore/UQMError.h>
|
||||
#import <CrashSightCore/UQMCompatLayer.h>
|
||||
#import <CrashSightCore/UQM.h>
|
||||
#import <CrashSightCore/UQMDefine.h>
|
||||
#import <CrashSightCore/UQMUtils.h>
|
||||
#import <CrashSightCore/UQMMacroExpand.h>
|
||||
#import <CrashSightCore/UQMSingleton.h>
|
||||
#import <CrashSightCore/UQMLog.h>
|
||||
#import <CrashSightCore/UQMThread.h>
|
||||
#import <CrashSightCore/UQMCrashIMPL.h>
|
||||
#import <CrashSightCore/UQMCrash.h>
|
||||
#import <CrashSightCore/UQMSynthesizeSingleton.h>
|
||||
#import <CrashSightCore/UQMUtilsIOS.h>
|
||||
#import <CrashSightCore/UQMCrashDelegate.h>
|
||||
#import <CrashSightCore/CrashSightBridge.h>
|
||||
#import <CrashSightCore/CrashSightMobileAgent.h>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef GCLOUD_VERSION_CRASHSIGHT
|
||||
#define GCLOUD_VERSION_CRASHSIGHT "GCLOUD_VERSION_CRASHSIGHT_4.3.8.1084" //用于编译时传入
|
||||
#endif
|
||||
|
||||
#include "UQMMacros.h"
|
||||
|
||||
//using namespace UQM;
|
||||
|
||||
namespace GCloud {
|
||||
namespace CrashSight {
|
||||
|
||||
enum LogSeverity
|
||||
{
|
||||
LogSilent,
|
||||
LogError,
|
||||
LogWarning,
|
||||
LogInfo,
|
||||
LogDebug,
|
||||
LogVerbose
|
||||
};
|
||||
|
||||
class UQM_EXPORT CrashSightMobileAgent
|
||||
{
|
||||
public:
|
||||
|
||||
/// Set game type for Android
|
||||
/// @param gameType COCOS=1, UNITY=2, UNREAL=3
|
||||
static void SetGameType(int gameType);
|
||||
|
||||
/// configs callback type.
|
||||
/// @param callbackType 目前是5种类型,用5位表示。第一位表示crash,第二位表示anr,第三位表示u3d c# error,第四位表示js,第五位表示lua
|
||||
static void ConfigCallbackType(int32_t callbackType);
|
||||
|
||||
/// Configs the default.
|
||||
/// @param channel channel
|
||||
/// @param version version
|
||||
/// @param user user
|
||||
/// @param delay delay
|
||||
static void ConfigDefault(const char* channel, const char* version, const char* user, long delay);
|
||||
|
||||
/// Configs the crashServerUrl.
|
||||
/// @param crashServerUrl crashServerUrl
|
||||
static void ConfigCrashServerUrl(const char* crashServerUrl);
|
||||
|
||||
/// Configs the type of the crash reporter and customized log level to upload
|
||||
/// @param logLevel Off=0,Error=1,Warn=2,Info=3,Debug=4
|
||||
static void ConfigCrashReporter(int logLevel);
|
||||
|
||||
/// configs the debug mode.
|
||||
/// @param enable If set to true< debug mode.
|
||||
static void ConfigDebugMode(bool enable);
|
||||
|
||||
/// Set deviceId.
|
||||
/// @param deviceId 设备唯一标识
|
||||
static void SetDeviceId(const char* deviceId);
|
||||
|
||||
/// Set app deviceId.
|
||||
/// @param deviceId
|
||||
static void SetCustomizedDeviceID(const char* deviceId);
|
||||
|
||||
static void GetSDKDefinedDeviceID(void* data, int len);
|
||||
|
||||
static void SetCustomizedMatchID(const char* matchId);
|
||||
|
||||
static void GetSDKSessionID(void* data, int len);
|
||||
|
||||
/// Set deviceModel.
|
||||
/// @param deviceModel 手机型号
|
||||
static void SetDeviceModel(const char* deviceModel);
|
||||
|
||||
/// 设置日志绝对路径.
|
||||
/// @param logPath 日志路径
|
||||
static void SetLogPath(const char* logPath);
|
||||
|
||||
/// Init sdk with the specified appId.
|
||||
/// @param appId App identifier.
|
||||
static void InitWithAppId(const char* appId, bool forceOnUiThread);
|
||||
|
||||
static void ReportExceptionPRV(int type, const char* exceptionName, const char* exceptionMsg, const char* exceptionStack, const char *extInfo, const char* extInfoJsonStr, bool quit = false, int dumpNativeType = 0, const char* errorAttachmentPath = "");
|
||||
|
||||
/// Report Exception
|
||||
/// @param type type
|
||||
/// @param name name
|
||||
/// @param reason reason
|
||||
/// @param stackTrace stackTrace
|
||||
/// @param extras extras, json对象序列化字符串
|
||||
/// @param quit quit
|
||||
/// @param dumpNativeType 0:关闭,1:调用系统接口dump,3:minidump
|
||||
static void ReportException(int type, const char* name, const char* reason, const char* stackTrace, const char* extras, bool quit, int dumpNativeType = 0, const char* errorAttachmentPath = "");
|
||||
|
||||
/// Report Exception
|
||||
/// @param type
|
||||
/// @param exceptionName
|
||||
/// @param exceptionMsg
|
||||
/// @param exceptionStack
|
||||
/// @param paramsJson map序列化后的JSON字符串
|
||||
/// @param dumpNativeType 0:关闭,1:调用系统接口dump,3:minidump
|
||||
static void ReportExceptionJson(int type, const char* exceptionName, const char* exceptionMsg, const char* exceptionStack, const char* paramsJson, int dumpNativeType = 0, const char* errorAttachmentPath = "");
|
||||
|
||||
/// Report log statistics
|
||||
/// @msgType 消息类型
|
||||
/// @msg 消息详情
|
||||
static void ReportLogInfo(const char* msgType, const char* msg);
|
||||
|
||||
/// Sets the user identifier.
|
||||
/// @param userId User identifier.
|
||||
static void SetUserId(const char* userId);
|
||||
|
||||
/// Sets the scene.
|
||||
/// @param sceneId Scene identifier.
|
||||
static void SetScene(const char *sceneId, bool upload = false);
|
||||
|
||||
/// Adds the scene data.
|
||||
/// @param key Key
|
||||
/// @param value Value
|
||||
static void AddSceneData(const char* key, const char* value);
|
||||
|
||||
/// Prints the log.
|
||||
/// @param level level
|
||||
/// @param format format
|
||||
static void PrintLog(LogSeverity level, const char* format, ...);
|
||||
|
||||
// unity android
|
||||
static void CloseCrashReport();
|
||||
|
||||
// unity android
|
||||
static void StartCrashReport();
|
||||
|
||||
// unity android
|
||||
static void RestartCrashReport();
|
||||
|
||||
/// Set app version.
|
||||
/// @param appVersion app version
|
||||
static void SetAppVersion(const char* appVersion);
|
||||
|
||||
|
||||
/// Catch multiple signal from different thread, and upload information of first signal.
|
||||
/// @param SetCatchMultiSignal enable
|
||||
static void SetCatchMultiSignal(bool enable);
|
||||
|
||||
/// Unwind at most 256 stack frame, and report last frame even if stack string is full.
|
||||
/// @param SetUnwindExtraStack enable
|
||||
static void SetUnwindExtraStack(bool enable);
|
||||
|
||||
/// Get crash thread id when crash happens. Return -1 while failed.
|
||||
static long GetCrashThreadId();
|
||||
|
||||
static bool IsLastSessionCrash();
|
||||
|
||||
static void GetLastSessionUserId(void* data, int len);
|
||||
|
||||
/// Set upload thread num, default 3
|
||||
static void SetUploadThreadNum(int num);
|
||||
|
||||
static void TestOomCrash();
|
||||
|
||||
static void TestJavaCrash();
|
||||
|
||||
static void TestOcCrash();
|
||||
|
||||
static void TestNativeCrash();
|
||||
|
||||
static void TestANR();
|
||||
|
||||
static void GetCrashUuid(void* data, int len);
|
||||
|
||||
static void SetLogcatBufferSize(int size);
|
||||
|
||||
static void startDumpRoutine(int dumpMode, int startTimeMode, long startTime, long dumpInterval,
|
||||
int dumpTimes, bool saveLocal, const char *savePath);
|
||||
|
||||
static void startMonitorFdCount(int interval, int limit, int dumpType);
|
||||
|
||||
static int getExceptionType(const char *name);
|
||||
|
||||
static void testUseAfterFree();
|
||||
|
||||
static void setEnableGetPackageInfo(bool enable);
|
||||
|
||||
static void setServerEnv(const char *serverEnv);
|
||||
|
||||
static void setEngineInfo(const char *version, const char *buildConfig, const char *language, const char *locale);
|
||||
|
||||
static void setGpuInfo(const char *version, const char *vendor, const char *renderer);
|
||||
|
||||
static void setIsOpengles(bool isOpengles);
|
||||
|
||||
static void enableDetailedPageTracing(bool enable);
|
||||
|
||||
static void useSavedUserId(bool enable);
|
||||
|
||||
static bool checkFdCount(int limit, int dumpType, bool upload);
|
||||
|
||||
static void SetOomLogPath(const char *logPath);
|
||||
|
||||
static void ReportJank(int type, const char* exceptionName,
|
||||
const char* exceptionMsg, const char* exceptionStack,
|
||||
const char* extInfoJsonStr, int reportInfoOption, const char* jankAttachmentPath = nullptr);
|
||||
|
||||
static void processEngineAnr(int type);
|
||||
|
||||
static void setEngineMainThread();
|
||||
|
||||
static void ReportStuck(int threadId, int maxChecks, long checkInterval,
|
||||
const char *name, const char *message, const char *extraInfo,
|
||||
int dumpNativeType, const char *attachPath);
|
||||
|
||||
private:
|
||||
static bool mIsInitialized;
|
||||
|
||||
static const char* GetCsVersion();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// UQM.h
|
||||
// CrashSight
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/4.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQM_h
|
||||
#define UQM_h
|
||||
|
||||
#include "UQMMacros.h"
|
||||
#include "UQMSingleton.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
//暂未弄清楚此处的具体用途,故不做替换修改
|
||||
#ifdef _WIN32
|
||||
#define UQM_ITOP_DEPRECATED(_version)
|
||||
#else
|
||||
#define UQM_ITOP_DEPRECATED(_version) __attribute__((deprecated))
|
||||
#endif
|
||||
|
||||
|
||||
class UQM : public UQMSingleton<UQM>
|
||||
{
|
||||
friend class UQMSingleton<UQM>;
|
||||
|
||||
private:
|
||||
UQM() {
|
||||
initialized = false;
|
||||
};
|
||||
virtual ~UQM();
|
||||
public:
|
||||
//JavaVM 是Android JNI使用,iOS这里定义一个,保证编译通过
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#define JavaVM void
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#define JavaVM void
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Initialize(JavaVM *vm);
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
// #include "UQMRename.h"
|
||||
|
||||
#endif /* UQM_h */
|
||||
|
|
@ -0,0 +1,515 @@
|
|||
//
|
||||
// UQMCompatLayer.hpp
|
||||
// Crashot
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMCompatLayer_hpp
|
||||
#define UQMCompatLayer_hpp
|
||||
|
||||
#include <sstream>
|
||||
#include "UQMMacros.h"
|
||||
#include "UQMMacroExpand.h"
|
||||
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#define uqm_strncpy(deestination,source,sourceLen) \
|
||||
do { \
|
||||
strncpy_s(deestination, sourceLen+1, source, sourceLen); \
|
||||
} while (0)
|
||||
#define uqm_strncat(deestination,source,sourceLen) \
|
||||
do {\
|
||||
strncat_s(deestination, sourceLen+1, source, sourceLen); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated"
|
||||
#endif
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
class UQMString
|
||||
{
|
||||
private:
|
||||
char *data;
|
||||
unsigned long len;
|
||||
|
||||
public:
|
||||
UQMString() : len(0)
|
||||
{
|
||||
data = UQM_SAFE_MALLOC(1, char);
|
||||
data[0] = '\0';
|
||||
}
|
||||
|
||||
UQMString(const std::string &str)
|
||||
{
|
||||
len = str.size();
|
||||
data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(data, str.c_str(), len);
|
||||
data[len] = '\0';
|
||||
}
|
||||
|
||||
UQMString(const char *strPtr)
|
||||
{
|
||||
if (strPtr == NULL)
|
||||
{
|
||||
len = 0;
|
||||
data = UQM_SAFE_MALLOC(1, char);
|
||||
data[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
len = (unsigned int) strlen(strPtr);
|
||||
data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(data, strPtr, len);
|
||||
data[len] = '\0';
|
||||
}
|
||||
|
||||
UQMString(const UQMString &str)
|
||||
{
|
||||
len = (unsigned int) str.size();
|
||||
data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(data, str.c_str(), len);
|
||||
data[len] = '\0';
|
||||
}
|
||||
|
||||
// 析构函数
|
||||
~UQMString()
|
||||
{
|
||||
UQM_SAFE_FREE(data);
|
||||
len = 0;
|
||||
}
|
||||
|
||||
// 重载+
|
||||
UQMString operator+(const UQMString &str) const
|
||||
{
|
||||
UQMString newStr;
|
||||
UQM_SAFE_FREE(newStr.data);
|
||||
newStr.len = len + (unsigned int) str.size();
|
||||
newStr.data = UQM_SAFE_MALLOC(newStr.len + 1, char);
|
||||
strncpy(newStr.data, data, len);
|
||||
strncat(newStr.data, str.data, str.length());
|
||||
newStr.data[newStr.len] = '\0';
|
||||
|
||||
return newStr;
|
||||
}
|
||||
|
||||
// 重载=
|
||||
UQMString &operator=(const UQMString &str)
|
||||
{
|
||||
if (this == &str)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
UQM_SAFE_FREE(data);
|
||||
len = str.len;
|
||||
data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(data, str.c_str(), len);
|
||||
data[len] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 重载=
|
||||
UQMString &operator=(const char *strPtr)
|
||||
{
|
||||
if (strPtr == NULL)
|
||||
{
|
||||
len = 0;
|
||||
data = UQM_SAFE_MALLOC(1, char);
|
||||
data[0] = '\0';
|
||||
return *this;
|
||||
}
|
||||
UQM_SAFE_FREE(data);
|
||||
len = (unsigned int) strlen(strPtr);
|
||||
data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(data, strPtr, len);
|
||||
data[len] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 重载=
|
||||
UQMString &operator=(const std::string &str)
|
||||
{
|
||||
UQM_SAFE_FREE(data);
|
||||
len = str.length();
|
||||
data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(data, str.c_str(), len);
|
||||
data[len] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 重载+=
|
||||
UQMString &operator+=(const UQMString &str)
|
||||
{
|
||||
len += str.len;
|
||||
char *new_data = UQM_SAFE_MALLOC(len + 1, char);
|
||||
strncpy(new_data, data, len);
|
||||
strncat(new_data, str.data,str.size());
|
||||
UQM_SAFE_FREE(data);
|
||||
data = new_data;
|
||||
data[len] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 重载==
|
||||
inline bool operator==(const UQMString &str) const
|
||||
{
|
||||
if (len != str.len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return strcmp(data, str.data) == 0;
|
||||
}
|
||||
|
||||
// 获取长度
|
||||
inline size_t size() const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
inline size_t length() const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
const std::string toString() const
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return size() <= 0;
|
||||
}
|
||||
|
||||
// 获取C字符串
|
||||
inline const char *c_str() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class UQMKVPair
|
||||
{
|
||||
public:
|
||||
UQMString key;
|
||||
UQMString value;
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
UQM_AutoParser("", O(key, value));
|
||||
#endif
|
||||
};
|
||||
|
||||
// 重新定义vector
|
||||
template<typename T, unsigned int SPARE_CAPACITY = 16>
|
||||
class UQMVector
|
||||
{
|
||||
public:
|
||||
//将构造函数声明为explicit ,是为了抑制由构造函数定义的隐式转换
|
||||
explicit UQMVector(unsigned long initSize = 0) : vectorSize(0), vectorCapacity(
|
||||
(unsigned int) initSize + SPARE_CAPACITY), objects(NULL)
|
||||
{
|
||||
objects = UQM_SAFE_MALLOC(initSize + SPARE_CAPACITY, T);
|
||||
|
||||
}
|
||||
|
||||
UQMVector(const UQMVector &rhs) : objects(NULL)
|
||||
{
|
||||
vectorSize = rhs.vectorSize;
|
||||
vectorCapacity = rhs.vectorCapacity;
|
||||
|
||||
objects = UQM_SAFE_MALLOC(vectorCapacity, T);
|
||||
for (unsigned int k = 0; k < vectorSize; k++)
|
||||
{
|
||||
objects[k] = rhs.objects[k];
|
||||
}
|
||||
}
|
||||
|
||||
~UQMVector()
|
||||
{
|
||||
for (unsigned int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
objects[i].~T();
|
||||
}
|
||||
UQM_SAFE_FREE(objects);
|
||||
}
|
||||
|
||||
const UQMVector &operator=(const UQMVector &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
for (unsigned int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
objects[i].~T();
|
||||
}
|
||||
UQM_SAFE_FREE(objects);
|
||||
vectorSize = rhs.vectorSize;
|
||||
vectorCapacity = rhs.vectorCapacity;
|
||||
|
||||
objects = UQM_SAFE_MALLOC(vectorCapacity, T);
|
||||
for (unsigned int k = 0; k < vectorSize; k++)
|
||||
{
|
||||
objects[k] = rhs.objects[k];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const UQMVector &operator=(const typename std::vector<T> &rhs)
|
||||
{
|
||||
if (!rhs.empty())
|
||||
{
|
||||
for (unsigned int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
objects[i].~T();
|
||||
}
|
||||
UQM_SAFE_FREE(objects);
|
||||
vectorSize = rhs.size();
|
||||
vectorCapacity = rhs.capacity();
|
||||
|
||||
objects = UQM_SAFE_MALLOC(vectorCapacity, T);
|
||||
for (unsigned int k = 0; k < vectorSize; k++)
|
||||
{
|
||||
objects[k] = rhs[k];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 如果index错误,直接返回0的数据
|
||||
T &operator[](int index)
|
||||
{
|
||||
if (index < 0 || index >= vectorSize)
|
||||
{
|
||||
return objects[0];
|
||||
}
|
||||
return objects[index];
|
||||
}
|
||||
|
||||
const T &operator[](int index) const
|
||||
{
|
||||
return objects[index];
|
||||
}
|
||||
|
||||
//检测是否需要扩容
|
||||
void reserve()
|
||||
{
|
||||
reserve(vectorSize);
|
||||
}
|
||||
|
||||
// 扩容数据
|
||||
void reserve(unsigned int newSize)
|
||||
{
|
||||
if (vectorCapacity > newSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
unsigned int newCapacity = newSize * 2 + 1;
|
||||
T *oldArr = objects;
|
||||
|
||||
objects = UQM_SAFE_MALLOC(newCapacity, T);
|
||||
for (unsigned int k = 0; k < vectorSize; k++)
|
||||
{
|
||||
objects[k] = oldArr[k];
|
||||
}
|
||||
vectorCapacity = newCapacity;
|
||||
for (unsigned int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
oldArr[i].~T();
|
||||
}
|
||||
UQM_SAFE_FREE(oldArr); // 删除原来的数据
|
||||
}
|
||||
|
||||
unsigned int size() const
|
||||
{
|
||||
return vectorSize;
|
||||
}
|
||||
|
||||
unsigned int capacity() const
|
||||
{
|
||||
return vectorCapacity;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return vectorSize == 0;
|
||||
}
|
||||
|
||||
bool find(const T &t) const
|
||||
{
|
||||
for (int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
if (objects[i] == t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void resize(unsigned int newSize)
|
||||
{
|
||||
reserve(newSize);
|
||||
vectorSize = newSize;
|
||||
}
|
||||
|
||||
void push_back(const T &obj)
|
||||
{
|
||||
reserve(); // 检测容器大小
|
||||
objects[vectorSize++] = obj;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
objects[vectorSize].~T();
|
||||
vectorSize--;
|
||||
}
|
||||
|
||||
const T &back() const
|
||||
{
|
||||
return objects[vectorSize - 1];
|
||||
}
|
||||
|
||||
const T *begin()
|
||||
{
|
||||
return &objects[0];
|
||||
}
|
||||
|
||||
T *end()
|
||||
{
|
||||
return &objects[vectorSize];
|
||||
}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
for (int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
objects[i].~T();
|
||||
}
|
||||
vectorSize = 0;
|
||||
UQM_SAFE_FREE(objects);
|
||||
objects = UQM_SAFE_MALLOC(SPARE_CAPACITY, T);
|
||||
vectorCapacity = SPARE_CAPACITY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const T *end() const
|
||||
{
|
||||
return &objects[vectorSize];
|
||||
}
|
||||
|
||||
std::string toString()
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Vector length:" << size() << ",capacity:" << capacity() << std::endl;
|
||||
for (int i = 0; i < vectorSize; i++)
|
||||
{
|
||||
out << "objects[" << i << "]:" << objects[i] << std::endl;
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
typedef T *iterator;
|
||||
private:
|
||||
unsigned int vectorSize;
|
||||
unsigned int vectorCapacity;
|
||||
T *objects;
|
||||
};
|
||||
|
||||
class UQMRetAdapter
|
||||
{
|
||||
public:
|
||||
|
||||
void convert(bool &val, const bool &innerVal);
|
||||
|
||||
void convert(double &val, const double &innerVal);
|
||||
|
||||
void convert(float &val, const float &innerVal);
|
||||
|
||||
void convert(int &val, const int &innerVal);
|
||||
|
||||
// void convert(long &val, const long &innerVal);
|
||||
|
||||
void convert(int64_t &val, const int64_t &innerVal);
|
||||
|
||||
void convert(std::string &val, const UQMString &innerVal)
|
||||
{
|
||||
val = innerVal.c_str();
|
||||
}
|
||||
|
||||
void convert(UQMString &innerVal, const std::string &val)
|
||||
{
|
||||
innerVal = val;
|
||||
}
|
||||
|
||||
void convert(std::map<std::string, std::string> &val, const UQMVector<UQMKVPair> &innerVal)
|
||||
{
|
||||
for (unsigned int i = 0; i < innerVal.size(); i++)
|
||||
{
|
||||
val.insert(std::make_pair(innerVal[i].key.c_str(), innerVal[i].value.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutTypeRet, typename InnerTypeRet>
|
||||
void convert(std::vector<OutTypeRet> &val, const UQMVector<InnerTypeRet> &innerVal)
|
||||
{
|
||||
size_t s = innerVal.size();
|
||||
val.resize(s);
|
||||
for (unsigned int i = 0; i < s; ++i)
|
||||
{
|
||||
convert(val[i], innerVal[i]); // operator[](size_t)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutTypeRet, typename InnerTypeRet>
|
||||
void convert(OutTypeRet &outTypeRet, const InnerTypeRet &innerTypeRet)
|
||||
{
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
outTypeRet.innerRetConvert(*this, innerTypeRet);
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
class UQM_EXPORT UQMCompatManager
|
||||
{
|
||||
public:
|
||||
template<typename OutTypeRet, typename InnerTypeRet>
|
||||
static bool compatConvert(OutTypeRet &outTypeRet, const InnerTypeRet &innerTypeRet)
|
||||
{
|
||||
UQMRetAdapter ret;
|
||||
ret.convert(outTypeRet, innerTypeRet);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif /* UQMCompatLayer_hpp */
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
//
|
||||
// UQMCrash.hpp
|
||||
// Version: 4.3.8(1084)
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMCrash_h
|
||||
#define UQMCrash_h
|
||||
|
||||
#include "UQMDefine.h"
|
||||
#include "CrashSightMobileAgent.h"
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
typedef enum {
|
||||
CRASH_TYPE_NATIVE = 2,
|
||||
CRASH_TYPE_U3D = 3,
|
||||
CRASH_TYPE_ANR = 4,
|
||||
CRASH_TYPE_JS = 5,
|
||||
CRASH_TYPE_LUA = 6,
|
||||
}UQMCrashType;
|
||||
|
||||
class UQM_EXPORT UQMCrashRet : public UQMBaseRet {
|
||||
public:
|
||||
int maxDataLen;
|
||||
char* data;
|
||||
};
|
||||
|
||||
class UQM_EXPORT UQMCrashObserver
|
||||
{
|
||||
public:
|
||||
//新增一个虚析构函数 不然 UE4 报错
|
||||
virtual ~UQMCrashObserver() {};
|
||||
|
||||
virtual long OnCrashExtraDataNotify(const UQMInnerCrashRet& crashRet) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
virtual const char* OnCrashExtraMessageNotify(int crashType) {
|
||||
return NULL;
|
||||
};
|
||||
};
|
||||
|
||||
class UQM_EXPORT UQMCrashLogObserver
|
||||
{
|
||||
public:
|
||||
//新增一个虚析构函数 不然 UE4 报错
|
||||
virtual ~UQMCrashLogObserver() {};
|
||||
|
||||
// 设置日志路径回调
|
||||
virtual const char* OnCrashSetLogPathNotify(int crashType) {
|
||||
return NULL;
|
||||
};
|
||||
|
||||
// 通知日志上传结果回调
|
||||
virtual void OnCrashLogUploadResultNotify(int crashType, int result) {
|
||||
};
|
||||
};
|
||||
|
||||
class UQM_EXPORT UQMCrash : public GCloud::CrashSight::CrashSightMobileAgent
|
||||
{
|
||||
private:
|
||||
static std::map<int, char*> retMsg;
|
||||
#if !UQM_PLATFORM_WINDOWS
|
||||
static pthread_mutex_t mutex;
|
||||
#endif
|
||||
|
||||
static void CrashDataObserver(const UQMInnerCrashRet& crashRet, const char* seqID);
|
||||
|
||||
static void CrashMessageObserver(const UQMInnerCrashRet& crashRet, const char* seqID);
|
||||
|
||||
static void CrashSetLogPathObserver(const UQMInnerCrashRet& crashRet, const char* seqID);
|
||||
|
||||
static void CrashLogUploadResultObserver(const UQMInnerCrashRet& crashRet, const char* seqID);
|
||||
|
||||
static UQMCrashObserver* mCrashObserver;
|
||||
static UQMCrashLogObserver* mCrashLogObserver;
|
||||
|
||||
~UQMCrash();
|
||||
|
||||
static void SetPRVCrashObserver(UQMInnerRetCallbackClass<UQMInnerCrashRet>::UQMInnerRetCallback crashObserver);
|
||||
static void SetExtraMessageCrashObserver(UQMInnerRetCallbackClass<UQMInnerCrashRet>::UQMInnerRetCallback crashObserver);
|
||||
static void SetLogPathObserver(UQMInnerRetCallbackClass<UQMInnerCrashRet>::UQMInnerRetCallback crashObserver);
|
||||
static void SetLogUploadResultObserver(UQMInnerRetCallbackClass<UQMInnerCrashRet>::UQMInnerRetCallback crashObserver);
|
||||
|
||||
public:
|
||||
static void SetCrashObserver(UQMCrashObserver* crashObserver);
|
||||
|
||||
static void SetCrashLogObserver(UQMCrashLogObserver* crashObserver);
|
||||
|
||||
/**
|
||||
* 配置回调类型
|
||||
* @param callbackType 目前是5种类型,用5位表示。第一位表示crash,第二位表示anr,第三位表示u3d c# error,第四位表示js,第五位表示lua
|
||||
* 示例:关闭u3d c# error上报(type=4)的回调, callbackType=0b11011
|
||||
*/
|
||||
static void ConfigCallbackTypeBeforeInit(int32_t callbackType);
|
||||
|
||||
/**
|
||||
* 崩溃处理函数处理超时限制
|
||||
* @param timeout <=0 表示不限制
|
||||
*/
|
||||
static void ConfigCrashHandleTimeout(int32_t timeout);
|
||||
|
||||
static void Init(const UQMString& appId, bool unexpectedTerminatingDetectionEnable, bool debugMode, const UQMString& serverUrl);
|
||||
/**
|
||||
* 自定义日志打印接口,用于记录一些关键的业务调试信息, 可以更全面地反应APP发生崩溃或异常的上下文环境.
|
||||
*
|
||||
* @param level 日志级别,0-silent, 1-error,2-warning,3-info,4-debug,5-verbose
|
||||
* @param tag 日志模块分类
|
||||
* @param log 日志内容
|
||||
*/
|
||||
static void LogInfo(int level, const UQMString& tag, const UQMString& log);
|
||||
|
||||
/**
|
||||
* 设置关键数据,随崩溃信息上报
|
||||
* @param key 键值
|
||||
* @param value 键值对
|
||||
*/
|
||||
static void SetUserValue(const UQMString& key, const UQMString& value);
|
||||
|
||||
/**
|
||||
* 设置用户 ID
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
static void SetUserId(const UQMString& userId);
|
||||
|
||||
/**
|
||||
* 设置App ID
|
||||
* @param appId 项目ID
|
||||
*/
|
||||
static void SetAppId(const UQMString& appId);
|
||||
|
||||
/**
|
||||
* 进入子地图
|
||||
* @param appId 项目ID
|
||||
*/
|
||||
static void EntrySubMap(const UQMString& appId);
|
||||
|
||||
/**
|
||||
* 设置场景
|
||||
* @param userSceneTag 场景标签
|
||||
*/
|
||||
static void SetUserSceneTag(const UQMString& userSceneTag, bool upload = false);
|
||||
|
||||
static void SetCurrentScene(int sceneId);
|
||||
|
||||
static void ReportExceptionPRV(int type, const UQMString& exceptionName, const UQMString& exceptionMsg, const UQMString& exceptionStack, const UQMVector<UQMKVPair>& extInfo, const UQMString& extInfoJsonStr, bool quit = false, int dumpNativeType = 0);
|
||||
|
||||
/**
|
||||
* 设置UQM的上报异常堆栈
|
||||
* @param type 3-cocoa 4-c# 5-JS 6-Lua, 7-统计信息上报
|
||||
* 当type=7时,exceptionName是统计的字段,exceptionMsg是统计字段的值
|
||||
* @param exceptionName 异常名称
|
||||
* @param exceptionMsg 异常消息
|
||||
* @param exceptionStack 异常堆栈内容
|
||||
* @param extInfo 异常的附加额外信息
|
||||
* @param dumpNativeType 0:关闭,1:调用系统接口dump,3:minidump
|
||||
*/
|
||||
static void ReportException(int type, const UQMString& exceptionName, const UQMString& exceptionMsg, const UQMString& exceptionStack, std::map<std::string, std::string>& extInfo, int dumpNativeType = 0)
|
||||
{
|
||||
UQMVector<UQMKVPair> tmp;
|
||||
std::map<std::string, std::string>::iterator it = extInfo.begin();
|
||||
for (; it != extInfo.end(); it++)
|
||||
{
|
||||
UQMKVPair kvPair;
|
||||
kvPair.key = (*it).first;
|
||||
kvPair.value = (*it).second;
|
||||
tmp.push_back(kvPair);
|
||||
}
|
||||
ReportExceptionPRV(type, exceptionName, exceptionMsg, exceptionStack, tmp,
|
||||
nullptr, false, dumpNativeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置UQM的上报异常堆栈: c接口版本,不支持map
|
||||
* @param type 3-cocoa 4-c# 5-JS 6-Lua
|
||||
* @param exceptionName 异常名称
|
||||
* @param exceptionMsg 异常消息
|
||||
* @param exceptionStack 异常堆栈内容
|
||||
* @param dumpNativeType 0:关闭,1:调用系统接口dump,3:minidump
|
||||
*/
|
||||
static void ReportException(int type, const UQMString& exceptionName, const UQMString& exceptionMsg, const UQMString& exceptionStack, int dumpNativeType = 0)
|
||||
{
|
||||
UQMVector<UQMKVPair> extInfo;
|
||||
ReportExceptionPRV(type, exceptionName, exceptionMsg, exceptionStack, extInfo, nullptr, false, dumpNativeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置前后台
|
||||
* @param isAppForeground 是否前台
|
||||
*/
|
||||
static void SetIsAppForeground(bool isAppForeground);
|
||||
|
||||
static void SetAppVersion(const UQMString& appVersion);
|
||||
|
||||
static void SetCallBackMsg(const UQMString &data);
|
||||
|
||||
// GameAgent
|
||||
static void InitWithAppId(const UQMString& appId);
|
||||
|
||||
static void ConfigDefaultBeforeInit(const UQMString& channel, const UQMString& version, const UQMString& user, long delay);
|
||||
|
||||
static void ConfigCrashServerUrlBeforeInit(const UQMString& crashServerUrl);
|
||||
|
||||
static void ConfigCrashReporterLogLevelBeforeInit(int logLevel);
|
||||
|
||||
static void ConfigDebugModeBeforeInit(bool enable);
|
||||
|
||||
static void SetDeviceId(const UQMString& deviceId);
|
||||
|
||||
static void SetCustomizedDeviceID(const UQMString& deviceId);
|
||||
|
||||
static void SetCustomizedMatchID(const UQMString& matchId);
|
||||
|
||||
static void SetDeviceModel(const UQMString& deviceModel);
|
||||
|
||||
static void SetLogPath(const UQMString& logPath);
|
||||
|
||||
static void ReportException(int type, const UQMString& name, const UQMString& reason, const UQMString& stackTrace, const UQMString& extras, bool quit, int dumpNativeType = 0)
|
||||
{
|
||||
UQMVector<UQMKVPair> tmp;
|
||||
UQMKVPair kvPair;
|
||||
kvPair.key = "Extra";
|
||||
kvPair.value = extras;
|
||||
tmp.push_back(kvPair);
|
||||
ReportExceptionPRV(type, name, reason, stackTrace, tmp, nullptr, quit, dumpNativeType);
|
||||
}
|
||||
|
||||
static void ReportExceptionJson(int type, const UQMString& exceptionName, const UQMString& exceptionMsg, const UQMString& exceptionStack, const UQMString& paramsJson, int dumpNativeType = 0)
|
||||
{
|
||||
UQMVector<UQMKVPair> tmp;
|
||||
ReportExceptionPRV(type, exceptionName, exceptionMsg, exceptionStack, tmp, paramsJson,
|
||||
false, dumpNativeType);
|
||||
}
|
||||
|
||||
static void LogRecord(int level, const UQMString& message);
|
||||
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMCrash_h */
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// UQMCrashDelegate.h
|
||||
// UQMCore
|
||||
//
|
||||
// Created by joyfyzhang on 2021/1/8.
|
||||
// Copyright © 2021 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMCrashDelegate_h
|
||||
#define UQMCrashDelegate_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol UQMCrashDelegate <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
- (void)configCallbackTypeBeforeInit: (int32_t)callbackType;
|
||||
|
||||
- (void)configCrashHandleTimeout: (int32_t)timeout;
|
||||
|
||||
- (void)initCrashReport:(NSString *)appId unexpectedTerminatingDetectionEnable:(bool)unexpectedTerminatingDetectionEnable debugMode:(bool)debugMode serverUrl:(NSString *)serverUrl;
|
||||
|
||||
@optional
|
||||
|
||||
- (void)reportLog:(int)level tag:(NSString *)tag log:(NSString *)log;
|
||||
|
||||
- (void)setUserData:(NSString *)key value:(NSString *)value;
|
||||
|
||||
- (void)setUserId: (NSString *)userId;
|
||||
|
||||
- (void)setAppId: (NSString *)appId;
|
||||
|
||||
- (void)setUserSceneTag: (NSString *)userSceneTag isUpload:(bool)upload;
|
||||
|
||||
- (void)reportException:(int)type exceptionName:(NSString *)exceptionName
|
||||
exceptionMsg:(NSString *)exceptionMsg
|
||||
exceptionStack:(NSString *)exceptionStack
|
||||
extInfo:(NSDictionary *)extInfo
|
||||
extInfoJsonStr:(NSString *)extInfoJsonStr
|
||||
quit:(bool)quit
|
||||
dumpNativeType:(int)dumpNativeType
|
||||
errorAttachmentPath:(NSString *)errorAttachmentPath;
|
||||
|
||||
-(void)reportLogInfo:(NSString*)msgType msg:(NSString*)msg;
|
||||
|
||||
- (void)setIsAppForeground: (bool)isAppForeground;
|
||||
|
||||
- (void)setAppVersion: (NSString *)appVersion;
|
||||
|
||||
// agent
|
||||
- (void)initWithAppId:(NSString *) appId;
|
||||
|
||||
- (void)configCrashServerUrlBeforeInit: (NSString *)serverUrl;
|
||||
|
||||
- (void)configDefaultBeforeInit: (NSString *)channel version:(NSString *)version user:(NSString *)user delay:(long)delay;
|
||||
|
||||
- (void)configCrashReporterLogLevelBeforeInit: (int)logLevel;
|
||||
|
||||
- (void)configDebugModeBeforeInit: (bool) enable;
|
||||
|
||||
- (void)logRecord: (int)level message: (NSString *)message;
|
||||
|
||||
- (void)setLogPath: (NSString *)logPath;
|
||||
|
||||
-(void)closeCrashReport;
|
||||
|
||||
-(void)reregisterCrashHandler;
|
||||
|
||||
- (long)getCrashThreadId;
|
||||
|
||||
- (void)setAppDeviceId: (NSString *)deviceId;
|
||||
|
||||
-(NSString*)getBackendDeviceId;
|
||||
|
||||
- (void)setCustomizedMatchID: (NSString *)matchId;
|
||||
|
||||
-(NSString*)getSDKSessionID;
|
||||
|
||||
-(BOOL)isLastSessionCrash;
|
||||
|
||||
-(NSString*)getLastSessionUserId;
|
||||
|
||||
-(int)getExceptionType:(NSString *)name;
|
||||
|
||||
-(void)setServerEnv:(NSString *)serverEnv;
|
||||
|
||||
-(void)setEngineInfo:(NSString *)version buildConfig:(NSString *)buildConfig language:(NSString *)language locale:(NSString *)locale;
|
||||
|
||||
- (void)enableDetailedPageTracing: (bool) enable;
|
||||
|
||||
- (void)useSavedUserId: (bool) enable;
|
||||
|
||||
- (void)setOomLogPath: (NSString *)logPath;
|
||||
|
||||
-(void)reportJank:(int)type exceptionName:(NSString *)name exceptionMsg:(NSString *) msg exceptionStack:(NSString *)stack extInfoJsonStr:(NSString *)extra reportInfoOption:(int)reportInfoOption jankAttachmentPath:(NSString *)attachPath;
|
||||
|
||||
-(void)reportStuckWithThreadIndex:(int)threadIndex
|
||||
maxChecks:(int)maxChecks
|
||||
checkInterval:(NSTimeInterval)checkInterval
|
||||
name:(NSString *)name
|
||||
message:(NSString *)message
|
||||
extraInfo:(NSString *)extraInfo
|
||||
dumpNativeType:(int)dumpNativeType
|
||||
attachPath:(NSString *)attachPath;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* UQMCrashDelegate_h */
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
//
|
||||
// UQMCrashIMPL.h
|
||||
// CrashSight
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/4.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMCrashIMPL_h
|
||||
#define UQMCrashIMPL_h
|
||||
|
||||
#include "UQMDefine.h"
|
||||
#include "UQMSingleton.h"
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
class UQMCrashIMPL : public UQMSingleton<UQMCrashIMPL>
|
||||
{
|
||||
friend class UQMSingleton<UQMCrashIMPL>;
|
||||
|
||||
public:
|
||||
|
||||
static void ConfigCallbackTypeBeforeInit(const std::string& channel, int32_t callbackType);
|
||||
|
||||
static void ConfigCrashHandleTimeout(const std::string& channel, int32_t timeout);
|
||||
|
||||
static bool Init(const std::string& channel, const std::string& appId, bool unexpectedTerminatingDetectionEnable, bool debugMode, const std::string& serverUrl);
|
||||
|
||||
static void LogInfo(const std::string& channel, int level, const std::string& tag, const std::string& log);
|
||||
|
||||
static void SetUserValue(const std::string& channel, const std::string& key, const std::string& value);
|
||||
|
||||
static void SetUserId(const std::string& channel, const std::string& userId);
|
||||
|
||||
static void SetAppId(const std::string& channel, const std::string& appId);
|
||||
|
||||
static void SetUserSceneTag(const std::string& channel, const std::string& userSceneTag, bool upload);
|
||||
|
||||
static void ReportException(const std::string& channel, int type, const std::string& exceptionName, const std::string& exceptionMsg, const std::string& exceptionStack, const UQMVector<UQMKVPair> &extInfo, const std::string& extInfoJsonStr, bool quit= false, int dumpNativeType= 0, const std::string& errorAttachmentPath = "");
|
||||
|
||||
static void ReportLogInfo(const std::string& msgType, const std::string& msg);
|
||||
|
||||
#ifdef ANDROID
|
||||
static jobject convert(const std::map<std::string, std::string> &data);
|
||||
#endif
|
||||
|
||||
static void SetIsAppForeground(const std::string& channel, bool isAppForeground);
|
||||
|
||||
static void SetAppVersion(const std::string& channel, const std::string& appVersion);
|
||||
|
||||
//测试接口
|
||||
static void TestOomCrash(const std::string& channel);
|
||||
static void TestJavaCrash(const std::string& channel);
|
||||
static void TestOcCrash(const std::string& channel);
|
||||
static void TestNativeCrash(std::string channel) {
|
||||
UQM_LOG_DEBUG("TestNativeCrash channel = %s", channel.c_str());
|
||||
abort();
|
||||
}
|
||||
static void TestANR(const std::string& channel);
|
||||
|
||||
//agent
|
||||
static bool InitWithAppId (const std::string& channel, const std::string& appId, bool forceOnUiThread);
|
||||
|
||||
static void SetGameType(const std::string& channel, int gameType);
|
||||
|
||||
static void ConfigDefaultBeforeInit(const std::string& channel, const std::string& appChannel, const std::string& version, const std::string& user, long delay);
|
||||
|
||||
static void ConfigCrashServerUrlBeforeInit(const std::string& channel, const std::string& serverUrl);
|
||||
|
||||
static void ConfigCrashReporterLogLevelBeforeInit(const std::string& channel, int logLevel);
|
||||
|
||||
static void ConfigDebugModeBeforeInit(const std::string& channel, bool enable);
|
||||
|
||||
static void SetDeviceId(const std::string& channel, const std::string& deviceId);
|
||||
|
||||
static void SetAppDeviceId(const std::string& channel, const std::string& deviceId);
|
||||
|
||||
static std::string GetBackendDeviceId(const std::string& channel);
|
||||
|
||||
static void SetCustomizedMatchID(const std::string& channel, const std::string& matchId);
|
||||
|
||||
static std::string GetSDKSessionID(const std::string& channel);
|
||||
|
||||
static void SetDeviceModel(const std::string& channel, const std::string& deviceModel);
|
||||
|
||||
static void SetLogPath(const std::string& channel, const std::string& logPath);
|
||||
|
||||
static void LogRecord (const std::string& channel, int level, const std::string& message);
|
||||
|
||||
static void CloseCrashReport(const std::string& channel);
|
||||
|
||||
static void StartCrashReport(const std::string& channel);
|
||||
|
||||
static void SetCatchMultiSignal(const std::string& channel, bool enable);
|
||||
|
||||
static void SetUnwindExtraStack(const std::string& channel, bool enable);
|
||||
|
||||
static long GetCrashThreadId(const std::string& channel);
|
||||
|
||||
static std::string GetCrashUuid(const std::string &channel);
|
||||
|
||||
static bool IsLastSessionCrash(const std::string& channel);
|
||||
|
||||
static std::string GetLastSessionUserId(const std::string& channel);
|
||||
|
||||
static void SetUploadThreadNum(const std::string& channel, int num);
|
||||
|
||||
static void SetLogcatBufferSize(const std::string &channel, int size);
|
||||
|
||||
static void startDumpRoutine(const std::string& channel, int dumpMode, int startTimeMode, long startTime,
|
||||
long dumpInterval, int dumpTimes, bool saveLocal, const std::string& savePath);
|
||||
|
||||
static void startMonitorFdCount(const std::string& channel, int interval, int limit, int dumpType);
|
||||
|
||||
static int getExceptionType(const std::string& channel, const std::string& name);
|
||||
|
||||
static void testUseAfterFree(const std::string &channel);
|
||||
|
||||
static void setEnableGetPackageInfo(const std::string& channel, bool enable);
|
||||
|
||||
static void setServerEnv(const std::string& channel, const std::string& serverEnv);
|
||||
|
||||
static void setEngineInfo(const std::string& channel, const std::string& version, const std::string& buildConfig, const std::string& language, const std::string& locale);
|
||||
|
||||
static void setGpuInfo(const std::string& channel, const std::string& version, const std::string& vendor, const std::string& renderer);
|
||||
|
||||
static void setIsOpengles(const std::string& channel, bool isOpengles);
|
||||
|
||||
static void enableDetailedPageTracing(const std::string& channel, bool enable);
|
||||
|
||||
static void useSavedUserId(const std::string& channel, bool enable);
|
||||
|
||||
static bool checkFdCount(const std::string& channel, int limit, int dumpType, bool upload);
|
||||
|
||||
static void SetOomLogPath(const std::string& channel, const std::string& logPath);
|
||||
|
||||
static void ReportJank(const std::string& channel, int type, const std::string& exceptionName,
|
||||
const std::string& exceptionMsg, const std::string& exceptionStack,
|
||||
const std::string& extInfoJsonStr, int reportInfoOption, const std::string& jankAttachmentPath);
|
||||
|
||||
static void processEngineAnr(const std::string& channel, int type);
|
||||
|
||||
static void setEngineMainThread(const std::string& channel);
|
||||
|
||||
static void ReportStuck(const std::string& channel, int threadId, int maxChecks, long checkInterval,
|
||||
const std::string& name, const std::string& message, const std::string& extraInfo,
|
||||
int dumpNativeType, const std::string& attachPath);
|
||||
|
||||
private:
|
||||
UQMCrashIMPL() {}
|
||||
static void CallFunction(const std::string& channel, const std::string& functionName, bool enable);
|
||||
static long CallLongFunction(const std::string& channel, const std::string& functionName);
|
||||
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMCrashIMPL_h */
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
//
|
||||
// UQMDefine.hpp
|
||||
// CrashSight
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMDefine_hpp
|
||||
#define UQMDefine_hpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include "UQMMacros.h"
|
||||
#include "UQMMacroExpand.h"
|
||||
#include "UQMCompatLayer.h"
|
||||
#include "CSLogger.h"
|
||||
|
||||
#define CS_SDK_DEVICE_ID_LEN 64
|
||||
#define CS_SDK_USER_ID_LEN 64
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
typedef enum UQMMethodName {
|
||||
kUQMMethodNameUndefine = 000,
|
||||
kUQMMethodNameCrashExtraData = 1011,
|
||||
kUQMMethodNameCrashExtraMessage = 1012,
|
||||
kUQMMethodNameCrashSetLogPath = 1013,
|
||||
kUQMMethodNameCrashLogUploadResult = 1014,
|
||||
} UQMMethodName;
|
||||
|
||||
typedef enum UQMObserverID
|
||||
{
|
||||
kUQMObserverIDWakeUp = 107,
|
||||
}UQMObserverID;
|
||||
|
||||
class UQM_EXPORT UQMBaseRet {
|
||||
public:
|
||||
// 标记是从哪个方法过来
|
||||
int methodNameID;
|
||||
// UQM 返回码,详情可参考 UQMError.h
|
||||
int retCode;
|
||||
// UQM 描述信息
|
||||
std::string retMsg;
|
||||
// 第三方渠道返回码
|
||||
int thirdCode;
|
||||
// 第三方渠道描述信息
|
||||
std::string thirdMsg;
|
||||
// 扩展字段,保留
|
||||
std::string extraJson;
|
||||
|
||||
// 构造函数对外使用,必须包含在外部调用,否则会 crash
|
||||
UQMBaseRet();
|
||||
|
||||
// 构造函数对外使用,必须包含在外部调用,否则会 crash
|
||||
UQMBaseRet(int code);
|
||||
|
||||
// 构造函数对外使用,必须包含在外部调用,否则会 crash
|
||||
UQMBaseRet(int code, int tCode, std::string tMsg);
|
||||
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
UQM_AutoParser("com.uqm.crashsight.core.api.UQMRet", A(thirdCode, "ret"), A(thirdMsg, "msg"),
|
||||
O(methodNameID, retCode, retMsg, extraJson));
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 基础结构类
|
||||
*/
|
||||
class UQM_EXPORT UQMInnerBaseRet
|
||||
{
|
||||
public:
|
||||
|
||||
// 标记是从哪个方法过来
|
||||
int methodNameID;
|
||||
|
||||
// UQM 返回码,详情可参考 UQMError.h
|
||||
int retCode;
|
||||
|
||||
// UQM 描述信息
|
||||
UQMString retMsg;
|
||||
|
||||
// 第三方渠道返回码
|
||||
int thirdCode;
|
||||
|
||||
// 第三方渠道描述信息
|
||||
UQMString thirdMsg;
|
||||
|
||||
// 扩展字段,保留
|
||||
UQMString extraJson;
|
||||
|
||||
// 回调类型
|
||||
int crashType{};
|
||||
|
||||
// 构造函数
|
||||
UQMInnerBaseRet();
|
||||
|
||||
UQMInnerBaseRet(int retCode);
|
||||
|
||||
UQMInnerBaseRet(int retCode, int methodID);
|
||||
|
||||
UQMInnerBaseRet(int retCode, int thirdCode, const UQMString& thirdMsg);
|
||||
|
||||
UQMInnerBaseRet(int retCode, UQMString retMsg, int thirdCode, const UQMString& thirdMsg);
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
UQM_AutoParser("com.uqm.crashsight.core.api.UQMRet", A(thirdCode, "ret"),
|
||||
A(thirdMsg, "msg"), O(methodNameID, retCode, retMsg, extraJson));
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class UQMInnerCrashRet : public UQMInnerBaseRet
|
||||
{
|
||||
public:
|
||||
char *data{};
|
||||
int maxDataLen{};
|
||||
int *dataLen{};
|
||||
UQMInnerCrashRet();
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
UQM_AutoParser("com.uqm.crashsight.core.api.crash.UQMCrashRet",
|
||||
A(thirdCode, "ret"), A(thirdMsg, "msg"),
|
||||
A(extraJson, "extra"), O(retCode, retMsg, methodNameID),
|
||||
O(methodNameID));
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename RetType>
|
||||
class UQMInnerRetCallbackClass
|
||||
{
|
||||
public:
|
||||
typedef void (*UQMInnerRetCallback)(const RetType &ret, const char *seqID);
|
||||
};
|
||||
|
||||
template<typename RetType>
|
||||
class UQMCallBackParams
|
||||
{
|
||||
public:
|
||||
RetType mRet;
|
||||
unsigned int mObserverID;
|
||||
UQMString mSeqID;
|
||||
UQMCallBackParams(const RetType &ret, unsigned int observerID, UQMString seqID): mRet(ret), mObserverID(observerID), mSeqID(seqID){};
|
||||
};
|
||||
|
||||
void UQMInnerObserverHolderDispatch(void (*callback)(int result, void *args), void *context);
|
||||
|
||||
|
||||
template<typename RetType>
|
||||
class UQMInnerObserverHolder
|
||||
{
|
||||
private :
|
||||
static std::map<int, typename UQMInnerRetCallbackClass<RetType>::UQMInnerRetCallback> mObserverHolder;
|
||||
static std::map<std::string, UQMCallBackParams<RetType> > mTaskParamsHolder;
|
||||
static void cacheTask(std::string mSeqID, UQMCallBackParams<RetType> taskParams)
|
||||
{
|
||||
if (mSeqID.empty()){
|
||||
UQM_LOG_DEBUG("cacheTask failed for mSeqID is empty");
|
||||
return;
|
||||
}
|
||||
mTaskParamsHolder.insert(std::make_pair(mSeqID, taskParams));
|
||||
UQM_LOG_DEBUG("mTaskParamsHolder after insert %s", mSeqID.c_str());
|
||||
}
|
||||
static void commitCacheTask()
|
||||
{
|
||||
typename std::map<std::string, UQMCallBackParams<RetType> >::iterator iter;
|
||||
for (iter = mTaskParamsHolder.begin(); iter != mTaskParamsHolder.end(); ){
|
||||
UQMCallBackParams<RetType> taskParam = iter->second;
|
||||
if(CommitCacheToTaskQueue(taskParam.mRet, taskParam.mObserverID, taskParam.mSeqID)){
|
||||
mTaskParamsHolder.erase(iter++);
|
||||
UQM_LOG_DEBUG("mTaskParamsHolder size: %lu, after erase %s", (unsigned long)mTaskParamsHolder.size(), taskParam.mSeqID.c_str());
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
// UQM_LOG_DEBUG("mTaskParamsHolder size: %lu, after commitCacheTask", (unsigned long)mTaskParamsHolder.size());
|
||||
}
|
||||
public:
|
||||
static void CacheObserver(const unsigned int mObserverID, typename UQMInnerRetCallbackClass<RetType>::UQMInnerRetCallback observer)
|
||||
{
|
||||
if (mObserverHolder.find(mObserverID) != mObserverHolder.end())
|
||||
{
|
||||
// 如果已经存在就删除原来的 key,保证 key 对应的 value 是最新
|
||||
mObserverHolder.erase(mObserverID);
|
||||
}
|
||||
|
||||
mObserverHolder.insert(std::make_pair(mObserverID, observer));
|
||||
commitCacheTask();
|
||||
}
|
||||
|
||||
static void CommitToTaskQueueBackRet(const RetType &ret, const unsigned int observerID, const UQMString &seqID)
|
||||
{
|
||||
if (mObserverHolder.find(observerID) != mObserverHolder.end())
|
||||
{
|
||||
UQMInnerCrashRet innerCrashRet = static_cast<UQMInnerCrashRet>(ret);
|
||||
|
||||
//UQM_LOG_DEBUG("innerCrashRet %d %s %p %d", observerID, seqID.c_str(), innerCrashRet.data, innerCrashRet.maxDataLen);
|
||||
|
||||
mObserverHolder[observerID](ret, seqID.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static void CommitToTaskQueue(const RetType &ret, const unsigned int observerID, const UQMString &seqID)
|
||||
{
|
||||
UQMCallBackParams<RetType> *params = new UQMCallBackParams<RetType>(ret, observerID, seqID);
|
||||
|
||||
if(mObserverHolder.find(params->mObserverID) == mObserverHolder.end()){ // 当前没有setObserver,缓存回调
|
||||
UQM_LOG_DEBUG("Cache ObserverID %d", observerID);
|
||||
UQMCallBackParams<RetType> taskParams(params->mRet, params->mObserverID, params->mSeqID);
|
||||
cacheTask(params->mSeqID.toString(), taskParams);
|
||||
UQM_SAFE_DELETE(params);
|
||||
} else if (kUQMObserverIDWakeUp == observerID){ //wakeup 回调直接回调
|
||||
UQM_LOG_DEBUG("CallbackOnMainThread %d", observerID);
|
||||
CallbackOnMainThread(-1, params);
|
||||
} else {
|
||||
UQM_LOG_DEBUG("DispatchAsyncMainThread %d", observerID);
|
||||
UQMInnerObserverHolderDispatch(CallbackOnMainThread, params);
|
||||
}
|
||||
}
|
||||
|
||||
static bool CommitCacheToTaskQueue(const RetType &ret, const unsigned int observerID, const UQMString &seqID){
|
||||
UQMCallBackParams<RetType> *params = new UQMCallBackParams<RetType>(ret, observerID, seqID);
|
||||
if(mObserverHolder.find(params->mObserverID) != mObserverHolder.end()){
|
||||
UQM_LOG_DEBUG("DispatchAsyncMainThread %d", observerID);
|
||||
UQMInnerObserverHolderDispatch(CallbackOnMainThread, params);
|
||||
return true;
|
||||
}
|
||||
UQM_SAFE_DELETE(params);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void CallbackOnMainThread(int ret, void *args)
|
||||
{
|
||||
UQMCallBackParams<RetType> *params = (UQMCallBackParams<RetType> *)args;
|
||||
|
||||
if (mObserverHolder.find(params->mObserverID) != mObserverHolder.end())
|
||||
{
|
||||
UQM_LOG_DEBUG("observer address %p of observerID : %d", mObserverHolder[params->mObserverID], params->mObserverID);
|
||||
mObserverHolder[params->mObserverID](params->mRet, params->mSeqID.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
UQM_LOG_DEBUG("can not get inner callback for %u, make sure you have define", params->mObserverID);
|
||||
}
|
||||
|
||||
UQM_SAFE_DELETE(params);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<class RetType> std::map<int, typename UQMInnerRetCallbackClass<RetType>::UQMInnerRetCallback> UQMInnerObserverHolder<RetType>::mObserverHolder;
|
||||
template<class RetType> std::map<std::string, UQMCallBackParams<RetType> > UQMInnerObserverHolder<RetType>::mTaskParamsHolder;
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
typedef void (*FuncRunOnUIDelegate)(void *args);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMDefine_hpp */
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// UQMLog.hpp
|
||||
// Crashot
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMError_hpp
|
||||
#define UQMError_hpp
|
||||
|
||||
#include "UQMMacros.h"
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
class UQMError
|
||||
{
|
||||
public:
|
||||
/** 未知错误 */
|
||||
static const int UNKNOWN = -1;
|
||||
static const int SUCCESS = 0;
|
||||
static const int NO_ASSIGN = 1; /** 没有赋值 */
|
||||
static const int CANCEL = 2;
|
||||
static const int SYSTEM_ERROR = 3;
|
||||
static const int NETWORK_ERROR = 4;
|
||||
static const int UQM_SERVER_ERROR = 5; // UQM 后台返回错误,参考第三方错误码
|
||||
static const int TIMEOUT = 6;
|
||||
static const int NOT_SUPPORT = 7;
|
||||
static const int OPERATION_SYSTEM_ERROR = 8;
|
||||
static const int NEED_PLUGIN = 9;
|
||||
static const int NEED_LOGIN = 10;
|
||||
static const int INVALID_ARGUMENT = 11;
|
||||
static const int NEED_SYSTEM_PERMISSION = 12;
|
||||
static const int NEED_CONFIG = 13;
|
||||
static const int SERVICE_REFUSE = 14;
|
||||
static const int NEED_INSTALL_APP = 15;
|
||||
static const int APP_NEED_UPGRADE = 16;
|
||||
static const int INITIALIZE_FAILED = 17;
|
||||
static const int EMPTY_CHANNEL = 18;
|
||||
static const int FUNCTION_DISABLE = 19;
|
||||
static const int NEED_REALNAME = 20; // 需实名认证
|
||||
static const int REALNAME_FAIL = 21; // 实名认证失败
|
||||
static const int IN_PROGRESS = 22; // 上次操作尚未完成,稍后再试
|
||||
static const int API_DEPRECATED = 23;
|
||||
static const int LIBCURL_ERROR = 24;
|
||||
static const int FREQUENCY_LIMIT = 25; //频率限制
|
||||
static const int DINED_BY_APP = 26; // 被三方拒绝,需要查看具体的错误
|
||||
|
||||
/** 1000 ~ 1099 字段是 LOGIN 模块相关的错误码 */
|
||||
static const int LOGIN_UNKNOWN_ERROR = 1000;
|
||||
static const int LOGIN_NO_CACHED_DATA = 1001; // 本地没有登录缓存数据
|
||||
static const int LOGIN_CACHED_DATA_EXPIRED = 1002; //本地有缓存,但是该缓存已经失效
|
||||
static const int LOGIN_KEY_STORE_VERIFY_ERROR = 1004;
|
||||
static const int LOGIN_NEED_USER_DATA = 1005;
|
||||
|
||||
static const int LOGIN_NEED_USER_DATA_SERVER = 1010;
|
||||
static const int LOGIN_URL_USER_LOGIN = 1011; // 异账号:使用URL登陆成功
|
||||
static const int LOGIN_NEED_LOGIN = 1012; // 异账号:需要进入登陆页
|
||||
static const int LOGIN_NEED_SELECT_ACCOUNT = 1013; // 异账号:需要弹出异帐号提示
|
||||
static const int LOGIN_ACCOUNT_REFRESH = 1014; // 异账号:通过URL将票据刷新
|
||||
|
||||
static const int CONNECT_NO_CACHED_DATA = 1021; // 本地没有关联渠道登录缓存数据
|
||||
static const int CONNECT_CACHED_DATA_EXPIRED = 1022; //本地有缓存,但是该缓存已经失效
|
||||
static const int CONNECT_NO_MATCH_MAIN_OPENID = 1023; //关联账号与主账号不一致
|
||||
|
||||
/** 1100 ~ 1199 字段是 FRIEND 模块相关的错误码 */
|
||||
static const int FRIEND_UNKNOWN_ERROR = 1100;
|
||||
|
||||
/** 1200 ~ 1299 字段是 GROUP 模块相关的错误码 */
|
||||
static const int GROUP_UNKNOWN_ERROR = 1200;
|
||||
|
||||
/** 1300 ~ 1399 字段是 NOTICE 模块相关的错误码 */
|
||||
static const int NOTICE_UNKNOWN_ERROR = 1300;
|
||||
|
||||
/** 1400 ~ 1499 字段是 Push 模块相关的错误码 */
|
||||
static const int PUSH_RECEIVER_TEXT = 1400; // 收到推送消息
|
||||
static const int PUSH_NOTIFICATION_CLICK = 1401; // 在通知栏点击收到的消息
|
||||
static const int PUSH_NOTIFICATION_SHOW = 1402; // 收到通知之后,通知栏显示
|
||||
|
||||
/** 1500 ~ 1599 字段是 WEBVIEW 模块相关的错误码 */
|
||||
static const int WEBVIEW_UNKNOWN_ERROR = 1500;
|
||||
|
||||
static const int THIRD_ERROR = 9999;// 第三方错误情况,参考第三方错误码
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMError_hpp */
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
//
|
||||
// UQMLog.hpp
|
||||
// CrashSight
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMLog_hpp
|
||||
#define UQMLog_hpp
|
||||
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "UQMMacros.h"
|
||||
#include "UQMCompatLayer.h"
|
||||
#include "CSLogger.h"
|
||||
#if UQM_PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
// 定义此宏 会在 release 日志宏中打印日志到控制台
|
||||
#ifndef DEBUG
|
||||
#define DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef UQM_LOG_TAG
|
||||
#define UQM_LOG_TAG "[CrashSightPlugin-Native]"
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#define UQM_LOG_MAX_LENGTH 1023 //冗余一位,用于解决最后一个是汉字导致被截断的问题
|
||||
#elif defined(__APPLE__)
|
||||
#define UQM_LOG_MAX_LENGTH 4096
|
||||
#endif
|
||||
|
||||
|
||||
//#define __UQM_FILENAME1__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
|
||||
//#define __UQM_FILENAME2__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
|
||||
//#define __UQM_FILENAME__ (strrchr(__FILE__, '/') ? (__UQM_FILENAME1__):(__UQM_FILENAME2__))
|
||||
|
||||
//#ifdef UQM_NO_LOG_DEBUG
|
||||
//#define UQM_LOG_DEBUG(...)
|
||||
//#define UQM_LOG_ERROR(...)
|
||||
//#define UQM_LOG_JSON(level, ...)
|
||||
//#else
|
||||
//#define UQM_LOG_DEBUG(...) UQMLogger(kUQMLevelDebug, UQM_LOG_TAG, __UQM_FILENAME__, __FUNCTION__, __LINE__).console().writeLog(__VA_ARGS__)
|
||||
//#define UQM_LOG_ERROR(...) UQMLogger(kUQMLevelError, UQM_LOG_TAG, __UQM_FILENAME__, __FUNCTION__, __LINE__).console().writeLog(__VA_ARGS__)
|
||||
//#endif
|
||||
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
typedef enum {
|
||||
kUQMLevelDebug = 0, // 调试使用日志 精简日志,kLevelVerbose、kLevelInfo、kLevelWarn 都合并成Debug
|
||||
kUQMLevelError, // 错误日志
|
||||
} UQMLogLevel;
|
||||
|
||||
typedef struct {
|
||||
UQMLogLevel level;
|
||||
const char *tag;
|
||||
const char *fileName;
|
||||
const char *funcName;
|
||||
int line;
|
||||
#if UQM_PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||
#else
|
||||
struct timeval timeval;
|
||||
#endif
|
||||
long long pid;
|
||||
long long tid;
|
||||
long long mainTid;
|
||||
} UQMLogInfo;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class UQM_EXPORT UQMLogger {
|
||||
public:
|
||||
|
||||
UQMLogger(UQMLogLevel level, const char *tag, const char *fileName, const char *funcName, int line);
|
||||
|
||||
~UQMLogger();
|
||||
|
||||
// 是否打印日志到控制台
|
||||
UQMLogger &console();
|
||||
|
||||
#if UQM_PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||
UQMLogger &writeLog(const char *fmt, ...);
|
||||
#else
|
||||
// 此接口独立出来 - 方便后续格式化
|
||||
UQMLogger &writeLog(const char *fmt, ...)__attribute__((format(printf, 2, 3)));
|
||||
#endif
|
||||
|
||||
static void consoleFormatLogVA(const UQMLogInfo *info, const char *message);
|
||||
static void consoleFormatLog(const UQMLogInfo *info, const char *format);
|
||||
static void consoleLog(const int level, const char *resultLog, ...);
|
||||
|
||||
static long long getPid() {
|
||||
#if UQM_PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||
return -1;
|
||||
#else
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
static long long getTid() {
|
||||
#if UQM_PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||
return -1;
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
return -1;
|
||||
#else
|
||||
return pthread_self();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static long long getMainTid() {
|
||||
#if UQM_PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||
return -1;
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
return -1;
|
||||
#else
|
||||
return gettid();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
UQMLogInfo info;
|
||||
bool isConsole;
|
||||
UQMString curLogMsg;
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMLog_hpp */
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
//
|
||||
// UQMMacroExpand.hpp
|
||||
// Crashot
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMMacroExpand_hpp
|
||||
#define UQMMacroExpand_hpp
|
||||
|
||||
#include "UQMMacros.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "jni.h"
|
||||
#endif
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
#ifdef ANDROID //Android 才需要 JNI 到 struct 的互转
|
||||
// Java 到 struct 的代码模板
|
||||
#define JNI_2_STRUCT_FUNC_BEGIN(clazzName) \
|
||||
public: \
|
||||
template<typename JObject> \
|
||||
void jni2Struct(JObject& obj, jobject src, char const* cn = clazzName) {
|
||||
|
||||
#define CONVERTER_JNI_2_STRUCT_OPTIONAL(M) \
|
||||
obj.convert(#M, M, src, cn);
|
||||
|
||||
// 设置别名
|
||||
#define CONVERTER_JNI_2_STRUCT_ALIAS(M, A_NAME) CONVERTER_JNI_2_STRUCT_OPTIONAL(M)
|
||||
//obj.convert(A_NAME,M, src, cn);
|
||||
|
||||
// call father jni2Struct add by yuanchengsu
|
||||
#define CONVERTER_JNI_2_STRUCT_BASE(M) M::jni2Struct(obj,src,cn);
|
||||
|
||||
#define JNI_2_STRUCT_FUNC_END() }
|
||||
|
||||
|
||||
// struct 到 JNI 的代码模板
|
||||
#define STRUCT_2_JNI_FUNC_BEGIN(clazzName) \
|
||||
template <class CLASS> \
|
||||
void struct2JNI(CLASS& obj, const char *root, char const* cn = clazzName) const { \
|
||||
|
||||
#define CONVERTER_STRUCT_2_JNI_OPTIONAL(M) \
|
||||
obj.convert(#M, M, cn);
|
||||
|
||||
#define CONVERTER_STRUCT_2_JNI_ALIAS(M, A_NAME) CONVERTER_STRUCT_2_JNI_OPTIONAL(M)
|
||||
//obj.convert(A_NAME, M, cn);
|
||||
|
||||
//call father struct2JNI add by yuanchengsu
|
||||
#define CONVERTER_STRUCT_2_JNI_BASE(M) M::struct2JNI(obj,root,cn);
|
||||
|
||||
#define STRUCT_2_JNI_FUNC_END() }
|
||||
#endif
|
||||
|
||||
// json 到 struct 的代码模板
|
||||
#define JSON_2_STRUCT_FUNC_BEGIN() \
|
||||
public: \
|
||||
template<typename Doc> \
|
||||
void json2Struct(Doc& obj) {
|
||||
|
||||
#define CONVERTER_JSON_2_STRUCT_OPTIONAL(M) \
|
||||
obj[#M].convert(M);
|
||||
|
||||
// 设置别名
|
||||
#define CONVERTER_JSON_2_STRUCT_ALIAS(M, A_NAME) \
|
||||
obj[A_NAME].convert(M);
|
||||
|
||||
// call father json2Struct by yuanchengsu
|
||||
#define CONVERTER_JSON_2_STRUCT_BASE(M) M::json2Struct(obj);
|
||||
|
||||
// struct 到 json 的代码模板
|
||||
#define STRUCT_2_JSON_FUNC_BEGIN() \
|
||||
template <class CLASS> \
|
||||
void struct2Json(CLASS& obj, const char *root) const {
|
||||
|
||||
#define CONVERTER_STRUCT_2_JSON_OPTIONAL(M) \
|
||||
obj.convert(#M,M);
|
||||
|
||||
// 设置别名
|
||||
#define CONVERTER_STRUCT_2_JSON_ALIAS(M, A_NAME) \
|
||||
obj.convert(A_NAME,M); \
|
||||
|
||||
// call father struct2Json by yuanchengsu
|
||||
#define CONVERTER_STRUCT_2_JSON_BASE(M) M::struct2Json(obj,root);
|
||||
|
||||
#define STRUCT_AND_JSON_FUNC_END() }
|
||||
|
||||
|
||||
// 兼容层转换代码
|
||||
#define RET_AND_INNER_FUNC_BEGIN() \
|
||||
template <class Doc, class TypeRet> \
|
||||
void innerRetConvert(Doc& doc, const TypeRet &typeRet) {
|
||||
|
||||
#define CONVERTER_RET_AND_INNER_OPTIONAL(M) \
|
||||
doc.convert(M, typeRet.M);
|
||||
|
||||
// 设置别名
|
||||
#define CONVERTER_RET_AND_INNER_ALIAS(M, A_NAME) CONVERTER_RET_AND_INNER_OPTIONAL(M)
|
||||
|
||||
//call father innerRetConvert by yuanchengsu
|
||||
#define CONVERTER_RET_AND_INNER_BASE(M) M::innerRetConvert(doc,typeRet);
|
||||
|
||||
#define RET_AND_INNER_FUNC_END() }
|
||||
|
||||
|
||||
#define ARG_SEQ \
|
||||
_29,_28,_27,_26,_25,_24,_23,_22,_21,_20, \
|
||||
_19,_18,_17,_16,_15,_14,_13,_12,_11,_10, \
|
||||
_9, _8, _7, _6, _5, _4, _3, _2, _1
|
||||
|
||||
#define ARG_N(ACTION, \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
|
||||
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
|
||||
_21, _22, _23, _24, _25, _26, _27, _28, _29, NUMBER, ...) ACTION##NUMBER
|
||||
|
||||
#define WRAP_LEVEL_ONE(ACT, LIST, ...) ARG_N(LEVEL_ONE, __VA_ARGS__, LIST)(ACT, __VA_ARGS__)
|
||||
#define WRAP_LEVEL_TWO(ACT, LIST, ...) ARG_N(LEVEL_TWO, __VA_ARGS__, LIST)(ACT, __VA_ARGS__)
|
||||
|
||||
#define LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_##ACT##M
|
||||
#define LEVEL_ONE_1(ACT, M) LEVEL_ONE_DEF(ACT, M)
|
||||
#define LEVEL_ONE_2(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_1(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_3(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_2(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_4(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_3(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_5(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_4(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_6(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_5(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_7(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_6(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_8(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_7(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_9(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_8(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_10(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_9(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_11(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_10(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_12(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_11(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_13(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_12(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_14(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_13(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_15(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_14(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_16(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_15(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_17(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_16(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_18(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_17(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_19(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_18(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_20(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_19(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_21(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_20(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_22(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_21(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_23(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_22(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_24(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_23(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_25(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_24(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_26(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_25(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_27(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_26(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_28(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_27(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_29(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_28(ACT, __VA_ARGS__)
|
||||
#define LEVEL_ONE_30(ACT, M, ...) LEVEL_ONE_DEF(ACT, M) LEVEL_ONE_29(ACT, __VA_ARGS__)
|
||||
|
||||
#define LEVEL_TWO_DEF(ACT, M) CONVERTER_##ACT(M)
|
||||
#define LEVEL_TWO_1(ACT, M) LEVEL_TWO_DEF(ACT, M)
|
||||
#define LEVEL_TWO_2(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_1(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_3(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_2(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_4(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_3(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_5(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_4(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_6(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_5(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_7(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_6(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_8(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_7(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_9(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_8(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_10(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_9(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_11(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_10(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_12(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_11(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_13(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_12(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_14(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_13(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_15(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_14(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_16(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_15(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_17(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_16(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_18(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_17(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_19(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_18(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_20(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_19(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_21(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_20(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_22(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_21(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_23(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_22(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_24(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_23(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_25(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_24(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_26(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_25(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_27(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_26(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_28(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_27(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_29(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_28(ACT, __VA_ARGS__)
|
||||
#define LEVEL_TWO_30(ACT, M, ...) LEVEL_TWO_DEF(ACT, M) LEVEL_TWO_29(ACT, __VA_ARGS__)
|
||||
|
||||
// struct to string
|
||||
#define LEVEL_ONE_STRUCT_2_JNI_O(...) WRAP_LEVEL_TWO(STRUCT_2_JNI_OPTIONAL, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_STRUCT_2_JNI_A(M, A) CONVERTER_STRUCT_2_JNI_ALIAS(M,A)
|
||||
#define LEVEL_ONE_STRUCT_2_JSON_O(...) WRAP_LEVEL_TWO(STRUCT_2_JSON_OPTIONAL, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_STRUCT_2_JSON_A(M, A) CONVERTER_STRUCT_2_JSON_ALIAS(M,A)
|
||||
#define LEVEL_ONE_RET_AND_INNER_O(...) WRAP_LEVEL_TWO(RET_AND_INNER_OPTIONAL, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_RET_AND_INNER_A(M, A) CONVERTER_RET_AND_INNER_ALIAS(M,A)
|
||||
|
||||
|
||||
|
||||
|
||||
// string to struct
|
||||
#define LEVEL_ONE_JNI_2_STRUCT_O(...) WRAP_LEVEL_TWO(JNI_2_STRUCT_OPTIONAL, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_JNI_2_STRUCT_A(M, A) CONVERTER_JNI_2_STRUCT_ALIAS(M,A)
|
||||
#define LEVEL_ONE_JSON_2_STRUCT_O(...) WRAP_LEVEL_TWO(JSON_2_STRUCT_OPTIONAL, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_JSON_2_STRUCT_A(M, A) CONVERTER_JSON_2_STRUCT_ALIAS(M,A)
|
||||
|
||||
// fix inherit by yuanchengsu
|
||||
#define LEVEL_ONE_STRUCT_2_JSON_B(...) WRAP_LEVEL_TWO(STRUCT_2_JSON_BASE, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_RET_AND_INNER_B(...) WRAP_LEVEL_TWO(RET_AND_INNER_BASE, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_JSON_2_STRUCT_B(...) WRAP_LEVEL_TWO(JSON_2_STRUCT_BASE, ARG_SEQ, __VA_ARGS__)
|
||||
|
||||
#define LEVEL_ONE_JNI_2_STRUCT_B(...) WRAP_LEVEL_TWO(JNI_2_STRUCT_BASE, ARG_SEQ, __VA_ARGS__)
|
||||
#define LEVEL_ONE_STRUCT_2_JNI_B(...) WRAP_LEVEL_TWO(STRUCT_2_JNI_BASE, ARG_SEQ, __VA_ARGS__)
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#define UQM_AutoParser(clazzName, ...) \
|
||||
JNI_2_STRUCT_FUNC_BEGIN(clazzName) \
|
||||
WRAP_LEVEL_ONE(JNI_2_STRUCT_, ARG_SEQ, __VA_ARGS__) \
|
||||
JNI_2_STRUCT_FUNC_END() \
|
||||
\
|
||||
STRUCT_2_JNI_FUNC_BEGIN(clazzName) \
|
||||
WRAP_LEVEL_ONE(STRUCT_2_JNI_, ARG_SEQ, __VA_ARGS__) \
|
||||
STRUCT_2_JNI_FUNC_END() \
|
||||
\
|
||||
JSON_2_STRUCT_FUNC_BEGIN() \
|
||||
WRAP_LEVEL_ONE(JSON_2_STRUCT_, ARG_SEQ, __VA_ARGS__) \
|
||||
STRUCT_AND_JSON_FUNC_END() \
|
||||
\
|
||||
STRUCT_2_JSON_FUNC_BEGIN() \
|
||||
WRAP_LEVEL_ONE(STRUCT_2_JSON_, ARG_SEQ, __VA_ARGS__) \
|
||||
STRUCT_AND_JSON_FUNC_END() \
|
||||
\
|
||||
RET_AND_INNER_FUNC_BEGIN() \
|
||||
WRAP_LEVEL_ONE(RET_AND_INNER_, ARG_SEQ, __VA_ARGS__) \
|
||||
RET_AND_INNER_FUNC_END()
|
||||
#else
|
||||
|
||||
#define UQM_AutoParser(clazzName, ...) \
|
||||
JSON_2_STRUCT_FUNC_BEGIN() \
|
||||
WRAP_LEVEL_ONE(JSON_2_STRUCT_, ARG_SEQ, __VA_ARGS__) \
|
||||
STRUCT_AND_JSON_FUNC_END() \
|
||||
\
|
||||
STRUCT_2_JSON_FUNC_BEGIN() \
|
||||
WRAP_LEVEL_ONE(STRUCT_2_JSON_, ARG_SEQ, __VA_ARGS__) \
|
||||
STRUCT_AND_JSON_FUNC_END() \
|
||||
\
|
||||
RET_AND_INNER_FUNC_BEGIN() \
|
||||
WRAP_LEVEL_ONE(RET_AND_INNER_, ARG_SEQ, __VA_ARGS__) \
|
||||
RET_AND_INNER_FUNC_END()
|
||||
|
||||
#endif
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMMacroExpand_hpp */
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
//
|
||||
// UQMMacros.hpp
|
||||
// UQM
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMMacros_hpp
|
||||
#define UQMMacros_hpp
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <cwchar>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NS_UQM_BEGIN namespace UQM \
|
||||
{
|
||||
#define NS_UQM_END }
|
||||
#define USING_NS_UQM using namespace UQM;
|
||||
#else
|
||||
#define NS_UQM_BEGIN
|
||||
#define NS_UQM_END
|
||||
#define USING_NS_UQM
|
||||
#endif
|
||||
|
||||
|
||||
#define UQM_UUID_KEY_NAME "uqm_uuid"
|
||||
#define UQM_CONFIG_DEFAULT_GAME_ID "11"
|
||||
#define UQM_SEQ_ID_PRIMARY_KEY_NAME "uqm_seq_id_primary_key"
|
||||
|
||||
//适配 UE4 以及 Cocos 系统定义
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#undef UQM_PLATFORM_WINDOWS
|
||||
#define UQM_PLATFORM_WINDOWS 1
|
||||
#else
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#undef UQM_PLATFORM_WINDOWS
|
||||
#define UQM_PLATFORM_WINDOWS 1
|
||||
#elif defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#undef UQM_PLATFORM_WINDOWS
|
||||
#define UQM_PLATFORM_WINDOWS 0
|
||||
#if TARGET_OS_IOS || TARGET_OS_IPHONE
|
||||
#undef UQM_PLATFORM_MAC
|
||||
#define UQM_PLATFORM_MAC 0
|
||||
#else
|
||||
#undef UQM_PLATFORM_MAC
|
||||
#define UQM_PLATFORM_MAC 1
|
||||
#endif
|
||||
#else
|
||||
#undef UQM_PLATFORM_WINDOWS
|
||||
#define UQM_PLATFORM_WINDOWS 0
|
||||
#undef UQM_PLATFORM_MAC
|
||||
#define UQM_PLATFORM_MAC 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//UE4 环境
|
||||
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_IOS || PLATFORM_ANDROID
|
||||
#undef UQM_UE4
|
||||
#define UQM_UE4 1
|
||||
#endif
|
||||
|
||||
|
||||
////UE4 windows 游客登录需要做dll 函数导出的特殊处理
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#ifdef UQM_CORE
|
||||
#define UQM_EXPORT_UE __declspec(dllexport)
|
||||
#else
|
||||
#define UQM_EXPORT_UE __declspec(dllimport)
|
||||
#endif
|
||||
#define UQM_EXPORT
|
||||
#define UQM_HIDDEN
|
||||
#else
|
||||
#define UQM_EXPORT_UE
|
||||
#if __GNUC__ >= 4
|
||||
#if defined(__APPLE__)
|
||||
#ifdef UQM_UE4
|
||||
// #define UQM_EXPORT UQMCORE_API
|
||||
// #define UQM_HIDDEN UQMCORE_API
|
||||
#define UQM_EXPORT
|
||||
#define UQM_HIDDEN
|
||||
#else
|
||||
#define UQM_EXPORT
|
||||
#define UQM_HIDDEN
|
||||
#endif
|
||||
#elif defined(CRASHSIGHT_PS4) || defined(CRASHSIGHT_PS5)
|
||||
#define UQM_EXPORT __declspec(dllimport)
|
||||
#define UQM_HIDDEN
|
||||
#else
|
||||
#define UQM_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define UQM_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
#else
|
||||
#define UQM_EXPORT
|
||||
#define UQM_HIDDEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//UE4 Mac/Windows
|
||||
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
#ifdef ANDROID
|
||||
#define UQM_VERSION "5.4.000.5057"
|
||||
#define UQM_CUR_OS 1
|
||||
#elif defined(__APPLE__)
|
||||
#define UQM_CUR_OS 2
|
||||
#define UQM_VERSION "5.4.000.5057"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#define UQM_LABEL_KEYCHAIN_ENABLE "UQM_KEYCHAIN_ENABLE"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 删除单个指针和删除多个指针
|
||||
#define UQM_SAFE_DELETE(ptr) \
|
||||
do \
|
||||
{ \
|
||||
if (ptr != NULL) \
|
||||
{ \
|
||||
delete ptr; \
|
||||
ptr = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define UQM_SAFE_DELETE_ARR(ptr) \
|
||||
do \
|
||||
{ \
|
||||
if (ptr != NULL) \
|
||||
{ \
|
||||
delete[] ptr; \
|
||||
ptr = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// 分配内存和释放内存
|
||||
#define UQM_SAFE_MALLOC(num, type) (type *) calloc((num) , sizeof(type))
|
||||
#define UQM_SAFE_FREE(ptr) \
|
||||
do \
|
||||
{ \
|
||||
if (ptr != NULL) \
|
||||
{ \
|
||||
free(ptr); \
|
||||
ptr = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(deprecated)
|
||||
# define CS_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
# else
|
||||
# define CS_DEPRECATED(msg)
|
||||
# endif
|
||||
#else
|
||||
# define CS_DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
#endif /* UQMMacros_hpp */
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// UQMRename.h
|
||||
// Crashot
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMRename_h
|
||||
#define UQMRename_h
|
||||
|
||||
|
||||
#endif /* UQMRename_h */
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// UQMSingleton.hpp
|
||||
// Crashot
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMSingleton_hpp
|
||||
#define UQMSingleton_hpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include "UQMMacros.h"
|
||||
|
||||
template<class T>
|
||||
class UQMSingleton
|
||||
{
|
||||
protected:
|
||||
UQMSingleton() {};
|
||||
private:
|
||||
UQMSingleton(const UQMSingleton &) {};
|
||||
|
||||
UQMSingleton &operator=(const UQMSingleton &) {};
|
||||
static T *mInstance;
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
static pthread_mutex_t mMutex;
|
||||
#endif
|
||||
public:
|
||||
static T *GetInstance();
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
T *UQMSingleton<T>::GetInstance()
|
||||
{
|
||||
if (mInstance == NULL)
|
||||
{
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
pthread_mutex_lock(&mMutex);
|
||||
#endif
|
||||
if (mInstance == NULL)
|
||||
{
|
||||
T *tmp = new T();
|
||||
mInstance = tmp;
|
||||
}
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
#endif
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
#if UQM_PLATFORM_WINDOWS
|
||||
#else
|
||||
template<class T>
|
||||
pthread_mutex_t UQMSingleton<T>::mMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
T *UQMSingleton<T>::mInstance = NULL;
|
||||
|
||||
|
||||
#endif /* UQMSingleton_hpp */
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
//
|
||||
// UQMSynthesizeSingleton.h
|
||||
// UQMCore
|
||||
//
|
||||
// Created by Hillson Song on 5/14/18.
|
||||
// Copyright © 2018. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef SYNTHESIZE_SINGLETON_FOR_CLASS_H
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS_H
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Singleton
|
||||
|
||||
/* Synthesize Singleton For Class
|
||||
*
|
||||
* Creates a singleton interface for the specified class with the following methods:
|
||||
*
|
||||
* + (MyClass*) sharedInstance;
|
||||
* + (void) purgeSharedInstance;
|
||||
*
|
||||
* Calling sharedInstance will instantiate the class and swizzle some methods to ensure
|
||||
* that only a single instance ever exists.
|
||||
* Calling purgeSharedInstance will destroy the shared instance and return the swizzled
|
||||
* methods to their former selves.
|
||||
*
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* MyClass.h:
|
||||
* ========================================
|
||||
* #import "SynthesizeSingleton.h"
|
||||
*
|
||||
* @interface MyClass: SomeSuperclass
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);
|
||||
*
|
||||
* @end
|
||||
* ========================================
|
||||
*
|
||||
*
|
||||
* MyClass.m:
|
||||
* ========================================
|
||||
* #import "MyClass.h"
|
||||
*
|
||||
* @implementation MyClass
|
||||
*
|
||||
* SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass);
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* @end
|
||||
* ========================================
|
||||
*
|
||||
*
|
||||
* Note: Calling alloc manually will also initialize the singleton, so you
|
||||
* can call a more complex init routine to initialize the singleton like so:
|
||||
*
|
||||
* [[MyClass alloc] initWithParam:firstParam secondParam:secondParam];
|
||||
*
|
||||
* Just be sure to make such a call BEFORE you call "sharedInstance" in
|
||||
* your program.
|
||||
*/
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(__CLASSNAME__) \
|
||||
\
|
||||
+ (__CLASSNAME__*) sharedInstance; \
|
||||
+ (void) purgeSharedInstance;
|
||||
|
||||
|
||||
#define SYNTHESIZE_SINGLETON_FOR_CLASS(__CLASSNAME__) \
|
||||
\
|
||||
static __CLASSNAME__* volatile _##__CLASSNAME__##_sharedInstance = nil; \
|
||||
\
|
||||
+ (__CLASSNAME__*) sharedInstanceNoSynch \
|
||||
{ \
|
||||
return (__CLASSNAME__*) _##__CLASSNAME__##_sharedInstance; \
|
||||
} \
|
||||
\
|
||||
+ (__CLASSNAME__*) sharedInstanceSynch \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil == _##__CLASSNAME__##_sharedInstance) \
|
||||
{ \
|
||||
_##__CLASSNAME__##_sharedInstance = [[self alloc] init]; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
NSAssert2(1==0, @"SynthesizeSingleton: %@ ERROR: +(%@ *)sharedInstance method did not get swizzled.", self, self); \
|
||||
} \
|
||||
} \
|
||||
return (__CLASSNAME__*) _##__CLASSNAME__##_sharedInstance; \
|
||||
} \
|
||||
\
|
||||
+ (__CLASSNAME__*) sharedInstance \
|
||||
{ \
|
||||
return [self sharedInstanceSynch]; \
|
||||
} \
|
||||
\
|
||||
+ (id)allocWithZone:(NSZone*) zone \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if (nil == _##__CLASSNAME__##_sharedInstance) \
|
||||
{ \
|
||||
_##__CLASSNAME__##_sharedInstance = [super allocWithZone:zone]; \
|
||||
if(nil != _##__CLASSNAME__##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
return _##__CLASSNAME__##_sharedInstance; \
|
||||
} \
|
||||
\
|
||||
+ (void)purgeSharedInstance \
|
||||
{ \
|
||||
@synchronized(self) \
|
||||
{ \
|
||||
if(nil != _##__CLASSNAME__##_sharedInstance) \
|
||||
{ \
|
||||
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceSynch)); \
|
||||
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
|
||||
_##__CLASSNAME__##_sharedInstance = nil; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
- (id)copyWithZone:(NSZone *)zone \
|
||||
{ \
|
||||
return self; \
|
||||
} \
|
||||
\
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*!
|
||||
* @header UQMThread.h
|
||||
* @Version 2.0.0
|
||||
* @date 2018/4/25
|
||||
* @abstract
|
||||
* thread 的简单封装声明
|
||||
*
|
||||
* @copyright
|
||||
* Copyright © 2018年. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef UQM_THREAD_H
|
||||
#define UQM_THREAD_H
|
||||
|
||||
#include <sstream>
|
||||
#include "UQMLog.h"
|
||||
#include "UQMMacros.h"
|
||||
|
||||
NS_UQM_BEGIN
|
||||
/*
|
||||
* 设置当前线程名字
|
||||
* @param module 模块名称
|
||||
* 为使用iOS,只能在当前线程内调用
|
||||
*/
|
||||
bool thread_set_msdk_name(const std::string &module);
|
||||
|
||||
|
||||
#ifdef ANDROID
|
||||
/*
|
||||
* 线程获取自己的名字
|
||||
* @return 当前线程名称
|
||||
*/
|
||||
std::string thread_self_get_name();
|
||||
|
||||
|
||||
/*
|
||||
* 线程设置自己的名称
|
||||
*/
|
||||
bool thread_self_set_name(const std::string &name);
|
||||
#endif
|
||||
NS_UQM_END
|
||||
|
||||
#endif //UQM_THREAD_H
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// UQMUtils.hpp
|
||||
// Crashot
|
||||
//(内部使用)简单的工具类声明,目前包含:
|
||||
// 1. 生成通用唯一识别码
|
||||
// 2. 格式化输出 Json 字符串
|
||||
// 3. 字符串跟数字连接工具
|
||||
// 4. 类型转换工具,将一个类型的值 <InType> 转换为另一个类型 <OutType>
|
||||
// Created by joyfyzhang on 2020/9/3.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef UQMUtils_hpp
|
||||
#define UQMUtils_hpp
|
||||
|
||||
#include "UQMDefine.h"
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
class UQM_EXPORT UQMUtils
|
||||
{
|
||||
public:
|
||||
// 移除空格
|
||||
static const char *Trim(const char *name);
|
||||
};
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif /* UQMUtils_hpp */
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// UQMUtilsIOS.h
|
||||
// Crashot
|
||||
//
|
||||
// Created by joyfyzhang on 2020/9/4.
|
||||
// Copyright © 2020 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UQMDefine.h"
|
||||
|
||||
#define GET_NSSTRING(cString) [NSString stringWithCString:(cString.c_str()?cString:"").c_str() encoding:NSUTF8StringEncoding]
|
||||
|
||||
@interface UQMUtilsIOS : NSObject
|
||||
|
||||
/**
|
||||
* 将NSDictionary转为标准JSON字符串
|
||||
*
|
||||
* @param dict 目标字典
|
||||
* @param prettyPrint 生成的JSON数据是否使用空格
|
||||
*
|
||||
* @return 结果JSON字符串
|
||||
*/
|
||||
+ (NSString *)jsonStringFromDict:(NSDictionary *)dict prettyPrint:(BOOL)prettyPrint;
|
||||
|
||||
/**
|
||||
* KVPair vector => NSDictionary
|
||||
*
|
||||
* @param kvVector KVPair vector
|
||||
*
|
||||
* @return 字典
|
||||
*/
|
||||
+ (NSDictionary *)dictFromKVVector:(UQM::UQMVector<UQM::UQMKVPair>)kvVector;
|
||||
|
||||
/**
|
||||
* c++ map => NSDictionary
|
||||
*
|
||||
* @param kvMap std::map<std::string,std::string>
|
||||
*
|
||||
* @return 字典
|
||||
*/
|
||||
+ (NSDictionary *)dictFromKVMap:(std::map<std::string,std::string> &)kvMap;
|
||||
|
||||
///**
|
||||
// * 获取原始设备型号
|
||||
// *
|
||||
// * @return 设备型号
|
||||
// */
|
||||
//+ (NSString *)getCurrentDeviceModel;
|
||||
@end
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#include "UQMMacros.h"
|
||||
|
||||
NS_UQM_BEGIN
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_False 0
|
||||
#define cJSON_True 1
|
||||
#define cJSON_NULL 2
|
||||
#define cJSON_Number 3
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON {
|
||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
|
||||
int type; /* The type of the item, as above. */
|
||||
|
||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
||||
int valueint; /* The item's number, if type==cJSON_Number */
|
||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
||||
|
||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks {
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||
extern cJSON *cJSON_Parse(const char *value);
|
||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||
extern char * UQM_EXPORT cJSON_Print(cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void UQM_EXPORT cJSON_Delete(cJSON *c);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int cJSON_GetArraySize(cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateNull(void);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateTrue(void);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateFalse(void);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateBool(int b);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateNumber(double num);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateString(const char *string);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateArray(void);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateObject(void);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
|
||||
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
|
||||
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
|
||||
extern cJSON * UQM_EXPORT cJSON_CreateStringArray(const char **strings,int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void UQM_EXPORT cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
|
||||
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
|
||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
|
||||
|
||||
extern void cJSON_Minify(char *json);
|
||||
|
||||
/* Macros for creating things quickly. */
|
||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_UQM_END
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
framework module CrashSightCore {
|
||||
umbrella header "CrashSightCore.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4c6e924cfb5704911aeed9d27fd6722e
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
Exclude iOS: 0
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
AddToEmbeddedBinaries: true
|
||||
CompileFlags:
|
||||
FrameworkDependencies: Security;
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// CrashSight.h
|
||||
//
|
||||
// Created by joyfyzhang on 2021/1/8.
|
||||
// Copyright © 2021 joyfyzhang. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef CrashSight_h
|
||||
#define CrashSight_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CrashSightCore/CrashSightCore.h>
|
||||
|
||||
/**
|
||||
* 异常上报模块
|
||||
* - 命名规则:固定为 UQMCrash + 渠道
|
||||
* - 必须实现 UQMCrashDelegate
|
||||
*/
|
||||
@interface CrashSightPlugin : NSObject <UQMCrashDelegate>
|
||||
|
||||
/** 插件必须是的单例的,建议使用 UQM 提供的宏定义进行处理
|
||||
* 单例宏处理 - 头文件部分
|
||||
*/
|
||||
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(CrashSightPlugin)
|
||||
|
||||
@end
|
||||
|
||||
#endif /* CrashSight_h */
|
||||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
framework module CrashSightPlugin {
|
||||
umbrella header "CrashSightPlugin.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
2294
Tool/sdk_packages/CrashSight/0.0.2/Assets/PhxhSDK/ThirdParty/CrashSight/Scripts/CrashSightAgent.cs
vendored
Normal file
2294
Tool/sdk_packages/CrashSight/0.0.2/Assets/PhxhSDK/ThirdParty/CrashSight/Scripts/CrashSightAgent.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 34047571c56b3c94f92a828719fbabce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81a06a3bb7606664d93044a9c50eb28e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bca1e29d2ac885d428e49570f70a71c0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace GCloud.UQM
|
||||
{
|
||||
#region UQM
|
||||
/// <summary>
|
||||
/// 回调的范型
|
||||
/// </summary>
|
||||
public delegate void OnUQMRetEventHandler<T> (T ret);
|
||||
public delegate string OnUQMStringRetEventHandler<T> (T ret, T crashType);
|
||||
|
||||
public delegate string OnUQMStringRetSetLogPathEventHandler<T>(T ret, T crashType);
|
||||
public delegate void OnUQMRetLogUploadEventHandler<T>(T ret, T crashType, T result);
|
||||
|
||||
|
||||
public class UQM
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
public const string LibName = "CrashSight";
|
||||
#elif UNITY_IOS
|
||||
public const string LibName = "__Internal";
|
||||
#elif UNITY_STANDALONE_WIN
|
||||
#if UNITY_64//win64
|
||||
public const string LibName = "CrashSight64";
|
||||
#else//win32
|
||||
public const string LibName = "CrashSight";
|
||||
#endif
|
||||
#elif UNITY_STANDALONE_OSX
|
||||
public const string LibName = "CrashSight";
|
||||
#elif UNITY_XBOXONE
|
||||
public const string LibName = "CrashSightXbox";
|
||||
#elif UNITY_PS4 || UNITY_PS5
|
||||
public const string LibName = "libcs";
|
||||
#elif UNITY_SWITCH
|
||||
public const string LibName = "__Internal";
|
||||
#elif UNITY_STANDALONE_LINUX
|
||||
public const string LibName = "CrashSight";
|
||||
#elif UNITY_OPENHARMONY
|
||||
public const string LibName = "CrashSight";
|
||||
#else
|
||||
public const string LibName = "__Internal";
|
||||
#endif
|
||||
private static bool initialized;
|
||||
|
||||
public static bool isDebug = true;
|
||||
|
||||
/// <summary>
|
||||
/// UQM init,游戏开始的时候设置
|
||||
/// </summary>
|
||||
public static void Init()
|
||||
{
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
if (isDebug)
|
||||
UQMLog.SetLevel(UQMLog.Level.Log);
|
||||
else
|
||||
UQMLog.SetLevel(UQMLog.Level.Error);
|
||||
UQMLog.Log ("UQM initialed !");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 28b1e81b8fa4086468b902ed1d439949
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1707
Tool/sdk_packages/CrashSight/0.0.2/Assets/PhxhSDK/ThirdParty/CrashSight/Scripts/UQMCcore/UQM/UQMCrash.cs
vendored
Normal file
1707
Tool/sdk_packages/CrashSight/0.0.2/Assets/PhxhSDK/ThirdParty/CrashSight/Scripts/UQMCcore/UQM/UQMCrash.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23cacf0f55b6da543b1acb95f0e14ed3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b52276a529d7da24182db01f818363b1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace GCloud.UQM
|
||||
{
|
||||
public enum UQMMethodNameID
|
||||
{
|
||||
UQM_CRASH_CALLBACK_EXTRA_DATA = 1011,
|
||||
UQM_CRASH_CALLBACK_EXTRA_MESSAGE = 1012,
|
||||
UQM_CRASH_CALLBACK_SET_LOG_PATH = 1013,
|
||||
UQM_CRASH_CALLBACK_LOG_UPLOAD_RESULT = 1014
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 831d916e1a2a1e24abc60bb7258090ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
namespace GCloud.UQM
|
||||
{
|
||||
/// <summary>
|
||||
/// UQM log
|
||||
/// </summary>
|
||||
class UQMLog
|
||||
{
|
||||
/// <summary>
|
||||
/// UQM SDK Log level
|
||||
/// </summary>
|
||||
public enum Level
|
||||
{
|
||||
None = 0,
|
||||
Log,
|
||||
Warning,
|
||||
Error
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The level, Error by default
|
||||
/// </summary>
|
||||
private static Level level = Level.Error;
|
||||
|
||||
private const string header = "[CrashSightPlugin-Unity]";
|
||||
|
||||
/// <summary>
|
||||
/// Sets the level.
|
||||
/// </summary>
|
||||
/// <param name="l">Level</param>
|
||||
public static void SetLevel (Level l)
|
||||
{
|
||||
level = l;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
public static void Log (string message)
|
||||
{
|
||||
if (level <= Level.Log) {
|
||||
UnityEngine.Debug.Log (header + message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Warning the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
public static void LogWarning (string message)
|
||||
{
|
||||
if (level <= Level.Warning) {
|
||||
UnityEngine.Debug.LogWarning (header + message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Error the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
public static void LogError (string message)
|
||||
{
|
||||
if (level <= Level.Error) {
|
||||
UnityEngine.Debug.LogError (header + message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void FullLog (string message)
|
||||
{
|
||||
try {
|
||||
var counter = 0;
|
||||
const int step = 512;
|
||||
var all = message.Length;
|
||||
while (counter < all) {
|
||||
var start = counter;
|
||||
var length = start + step > all ? all - start : step;
|
||||
//UnityEngine.Debug.LogError(header + "all : " + all + " start : " + start + " length : " + length);
|
||||
UnityEngine.Debug.Log (header + message.Substring (start, length));
|
||||
counter += step;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
UnityEngine.Debug.LogWarning (e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2dacb082ac621aa4c9f4eedad0e683b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
using AOT;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace GCloud.UQM
|
||||
{
|
||||
public class RetArgsWrapper
|
||||
{
|
||||
private readonly int methodId;
|
||||
private readonly int crashType;
|
||||
private readonly int logUploadResult;
|
||||
|
||||
public int MethodId
|
||||
{
|
||||
get { return methodId; }
|
||||
}
|
||||
|
||||
public int CrashType
|
||||
{
|
||||
get { return crashType; }
|
||||
}
|
||||
|
||||
public int LogUploadResult
|
||||
{
|
||||
get { return logUploadResult; }
|
||||
}
|
||||
|
||||
public RetArgsWrapper(int _methodId, int _crashType, int _logUploadResult)
|
||||
{
|
||||
methodId = _methodId;
|
||||
crashType = _crashType;
|
||||
logUploadResult = _logUploadResult;
|
||||
}
|
||||
}
|
||||
|
||||
#region UQMMessageCenter
|
||||
|
||||
public class UQMMessageCenter : MonoBehaviour
|
||||
{
|
||||
#region json ret and callback
|
||||
|
||||
private static bool initialzed = false;
|
||||
|
||||
private delegate string UQMRetJsonEventHandler(int methodId, int callType, int logUploadResult);
|
||||
|
||||
[MonoPInvokeCallback(typeof(UQMRetJsonEventHandler))]
|
||||
public static string OnUQMRet(int methodId, int crashType, int logUploadResult)
|
||||
{
|
||||
var argsWrapper = new RetArgsWrapper(methodId, crashType, logUploadResult);
|
||||
UQMLog.Log("OnUQMRet, the methodId is ( " + methodId + " ) crashType=" + crashType);
|
||||
if (methodId == (int)UQMMethodNameID.UQM_CRASH_CALLBACK_EXTRA_MESSAGE
|
||||
|| methodId == (int)UQMMethodNameID.UQM_CRASH_CALLBACK_EXTRA_DATA
|
||||
|| methodId == (int)UQMMethodNameID.UQM_CRASH_CALLBACK_SET_LOG_PATH
|
||||
|| methodId == (int)UQMMethodNameID.UQM_CRASH_CALLBACK_LOG_UPLOAD_RESULT
|
||||
)
|
||||
{
|
||||
lock (CrashSightAgent.callbackThreadsLock) {
|
||||
CrashSightAgent.callbackThreads.Add(Thread.CurrentThread.ManagedThreadId);
|
||||
}
|
||||
string result = SynchronousDelegate(argsWrapper);
|
||||
lock (CrashSightAgent.callbackThreadsLock) {
|
||||
CrashSightAgent.callbackThreads.Remove(Thread.CurrentThread.ManagedThreadId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#if (UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_OPENHARMONY || UNITY_STANDALONE_LINUX) && !UNITY_EDITOR
|
||||
[DllImport(UQM.LibName, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void cs_setUnityCallback(UQMRetJsonEventHandler eventHandler);
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
static UQMMessageCenter instance;
|
||||
|
||||
public static UQMMessageCenter Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance != null) return instance;
|
||||
var bridgeGameObject = new GameObject { name = "UQMMessageCenter" };
|
||||
DontDestroyOnLoad(bridgeGameObject);
|
||||
instance = bridgeGameObject.AddComponent(typeof(UQMMessageCenter)) as UQMMessageCenter;
|
||||
UQMLog.Log("UQMMessageCenter instance=" + instance);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
#if (UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_OPENHARMONY || UNITY_STANDALONE_LINUX) && !UNITY_EDITOR
|
||||
if (initialzed) {
|
||||
return;
|
||||
}
|
||||
cs_setUnityCallback(OnUQMRet);
|
||||
initialzed = true;
|
||||
#endif
|
||||
UQMLog.Log("UQM Init, set unity callback");
|
||||
}
|
||||
|
||||
public void Uninit()
|
||||
{
|
||||
#if (UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_OPENHARMONY || UNITY_STANDALONE_LINUX) && !UNITY_EDITOR
|
||||
cs_setUnityCallback(null);
|
||||
#endif
|
||||
UQMLog.Log("UQM Uninit, set unity callback to null");
|
||||
}
|
||||
|
||||
static string SynchronousDelegate(object arg)
|
||||
{
|
||||
var argsWrapper = (RetArgsWrapper)arg;
|
||||
var methodId = argsWrapper.MethodId;
|
||||
var crashType = argsWrapper.CrashType;
|
||||
|
||||
UQMLog.Log("the methodId is ( " + methodId + " ) and crashType=" + crashType);
|
||||
switch (methodId)
|
||||
{
|
||||
#if UNITY_WSA
|
||||
#else
|
||||
case (int)UQMMethodNameID.UQM_CRASH_CALLBACK_EXTRA_MESSAGE:
|
||||
return UQMCrash.OnCrashCallbackMessage(methodId, crashType);
|
||||
|
||||
case (int)UQMMethodNameID.UQM_CRASH_CALLBACK_EXTRA_DATA:
|
||||
return UQMCrash.OnCrashCallbackData(methodId, crashType);
|
||||
|
||||
case (int)UQMMethodNameID.UQM_CRASH_CALLBACK_SET_LOG_PATH:
|
||||
return UQMCrash.OnCrashSetLogPathMessage(methodId, crashType);
|
||||
|
||||
case (int)UQMMethodNameID.UQM_CRASH_CALLBACK_LOG_UPLOAD_RESULT:
|
||||
return UQMCrash.OnCrashLogUploadMessage(methodId, crashType, argsWrapper.LogUploadResult);
|
||||
#endif
|
||||
}
|
||||
return "";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 524f6583d96f8ef4ca16ac5cf1e72745
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Calvin Rien
|
||||
*
|
||||
* Based on the JSON parser by Patrick van Bergen
|
||||
* http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
|
||||
*
|
||||
* Simplified it so that it doesn't throw exceptions
|
||||
* and can be used in Unity iOS with maximum code stripping.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace GCloud.UQM.MiniJSON
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class encodes and decodes JSON strings.
|
||||
/// Spec. details, see http://www.json.org/
|
||||
///
|
||||
/// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary.
|
||||
/// All numbers are parsed to doubles.
|
||||
/// </summary>
|
||||
public static class Json {
|
||||
/// <summary>
|
||||
/// Parses the string json into a value
|
||||
/// </summary>
|
||||
/// <param name="json">A JSON string.</param>
|
||||
/// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns>
|
||||
public static object Deserialize(string json) {
|
||||
// save the string for debug information
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Parser.Parse(json);
|
||||
}
|
||||
|
||||
sealed class Parser : IDisposable {
|
||||
const string WORD_BREAK = "{}[],:\"";
|
||||
|
||||
public static bool IsWordBreak(char c) {
|
||||
return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1;
|
||||
}
|
||||
|
||||
enum TOKEN {
|
||||
NONE,
|
||||
CURLY_OPEN,
|
||||
CURLY_CLOSE,
|
||||
SQUARED_OPEN,
|
||||
SQUARED_CLOSE,
|
||||
COLON,
|
||||
COMMA,
|
||||
STRING,
|
||||
NUMBER,
|
||||
TRUE,
|
||||
FALSE,
|
||||
NULL
|
||||
};
|
||||
|
||||
StringReader json;
|
||||
|
||||
Parser(string jsonString) {
|
||||
json = new StringReader(jsonString);
|
||||
}
|
||||
|
||||
public static object Parse(string jsonString) {
|
||||
using (var instance = new Parser(jsonString)) {
|
||||
return instance.ParseValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
json.Dispose();
|
||||
json = null;
|
||||
}
|
||||
|
||||
Dictionary<string, object> ParseObject() {
|
||||
Dictionary<string, object> table = new Dictionary<string, object>();
|
||||
|
||||
// ditch opening brace
|
||||
json.Read();
|
||||
|
||||
// {
|
||||
while (true) {
|
||||
switch (NextToken) {
|
||||
case TOKEN.NONE:
|
||||
return null;
|
||||
case TOKEN.COMMA:
|
||||
continue;
|
||||
case TOKEN.CURLY_CLOSE:
|
||||
return table;
|
||||
default:
|
||||
// name
|
||||
string name = ParseString();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// :
|
||||
if (NextToken != TOKEN.COLON) {
|
||||
return null;
|
||||
}
|
||||
// ditch the colon
|
||||
json.Read();
|
||||
|
||||
// value
|
||||
table[name] = ParseValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<object> ParseArray() {
|
||||
List<object> array = new List<object>();
|
||||
|
||||
// ditch opening bracket
|
||||
json.Read();
|
||||
|
||||
// [
|
||||
var parsing = true;
|
||||
while (parsing) {
|
||||
TOKEN nextToken = NextToken;
|
||||
|
||||
switch (nextToken) {
|
||||
case TOKEN.NONE:
|
||||
return null;
|
||||
case TOKEN.COMMA:
|
||||
continue;
|
||||
case TOKEN.SQUARED_CLOSE:
|
||||
parsing = false;
|
||||
break;
|
||||
default:
|
||||
object value = ParseByToken(nextToken);
|
||||
|
||||
array.Add(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
object ParseValue() {
|
||||
TOKEN nextToken = NextToken;
|
||||
return ParseByToken(nextToken);
|
||||
}
|
||||
|
||||
object ParseByToken(TOKEN token) {
|
||||
switch (token) {
|
||||
case TOKEN.STRING:
|
||||
return ParseString();
|
||||
case TOKEN.NUMBER:
|
||||
return ParseNumber();
|
||||
case TOKEN.CURLY_OPEN:
|
||||
return ParseObject();
|
||||
case TOKEN.SQUARED_OPEN:
|
||||
return ParseArray();
|
||||
case TOKEN.TRUE:
|
||||
return true;
|
||||
case TOKEN.FALSE:
|
||||
return false;
|
||||
case TOKEN.NULL:
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
string ParseString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
char c;
|
||||
|
||||
// ditch opening quote
|
||||
json.Read();
|
||||
|
||||
bool parsing = true;
|
||||
while (parsing) {
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
c = NextChar;
|
||||
switch (c) {
|
||||
case '"':
|
||||
parsing = false;
|
||||
break;
|
||||
case '\\':
|
||||
if (json.Peek() == -1) {
|
||||
parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
c = NextChar;
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
s.Append(c);
|
||||
break;
|
||||
case 'b':
|
||||
s.Append('\b');
|
||||
break;
|
||||
case 'f':
|
||||
s.Append('\f');
|
||||
break;
|
||||
case 'n':
|
||||
s.Append('\n');
|
||||
break;
|
||||
case 'r':
|
||||
s.Append('\r');
|
||||
break;
|
||||
case 't':
|
||||
s.Append('\t');
|
||||
break;
|
||||
case 'u':
|
||||
var hex = new char[4];
|
||||
|
||||
for (int i=0; i< 4; i++) {
|
||||
hex[i] = NextChar;
|
||||
}
|
||||
|
||||
s.Append((char) Convert.ToInt32(new string(hex), 16));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
s.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s.ToString();
|
||||
}
|
||||
|
||||
object ParseNumber() {
|
||||
string number = NextWord;
|
||||
|
||||
if (number.IndexOf('.') == -1) {
|
||||
long parsedInt;
|
||||
Int64.TryParse(number, out parsedInt);
|
||||
return parsedInt;
|
||||
}
|
||||
|
||||
double parsedDouble;
|
||||
Double.TryParse(number, out parsedDouble);
|
||||
return parsedDouble;
|
||||
}
|
||||
|
||||
void EatWhitespace() {
|
||||
while (Char.IsWhiteSpace(PeekChar)) {
|
||||
json.Read();
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char PeekChar {
|
||||
get {
|
||||
return Convert.ToChar(json.Peek());
|
||||
}
|
||||
}
|
||||
|
||||
char NextChar {
|
||||
get {
|
||||
return Convert.ToChar(json.Read());
|
||||
}
|
||||
}
|
||||
|
||||
string NextWord {
|
||||
get {
|
||||
StringBuilder word = new StringBuilder();
|
||||
|
||||
while (!IsWordBreak(PeekChar)) {
|
||||
word.Append(NextChar);
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return word.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
TOKEN NextToken {
|
||||
get {
|
||||
EatWhitespace();
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
return TOKEN.NONE;
|
||||
}
|
||||
|
||||
switch (PeekChar) {
|
||||
case '{':
|
||||
return TOKEN.CURLY_OPEN;
|
||||
case '}':
|
||||
json.Read();
|
||||
return TOKEN.CURLY_CLOSE;
|
||||
case '[':
|
||||
return TOKEN.SQUARED_OPEN;
|
||||
case ']':
|
||||
json.Read();
|
||||
return TOKEN.SQUARED_CLOSE;
|
||||
case ',':
|
||||
json.Read();
|
||||
return TOKEN.COMMA;
|
||||
case '"':
|
||||
return TOKEN.STRING;
|
||||
case ':':
|
||||
return TOKEN.COLON;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
return TOKEN.NUMBER;
|
||||
}
|
||||
|
||||
switch (NextWord) {
|
||||
case "false":
|
||||
return TOKEN.FALSE;
|
||||
case "true":
|
||||
return TOKEN.TRUE;
|
||||
case "null":
|
||||
return TOKEN.NULL;
|
||||
}
|
||||
|
||||
return TOKEN.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
|
||||
/// </summary>
|
||||
/// <param name="json">A Dictionary<string, object> / List<object></param>
|
||||
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
|
||||
public static string Serialize(object obj) {
|
||||
return Serializer.Serialize(obj);
|
||||
}
|
||||
|
||||
sealed class Serializer {
|
||||
StringBuilder builder;
|
||||
|
||||
Serializer() {
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
|
||||
public static string Serialize(object obj) {
|
||||
var instance = new Serializer();
|
||||
|
||||
instance.SerializeValue(obj);
|
||||
|
||||
return instance.builder.ToString();
|
||||
}
|
||||
|
||||
void SerializeValue(object value) {
|
||||
IList asList;
|
||||
IDictionary asDict;
|
||||
string asStr;
|
||||
|
||||
if (value == null) {
|
||||
builder.Append("null");
|
||||
} else if ((asStr = value as string) != null) {
|
||||
SerializeString(asStr);
|
||||
} else if (value is bool) {
|
||||
builder.Append((bool) value ? "true" : "false");
|
||||
} else if ((asList = value as IList) != null) {
|
||||
SerializeArray(asList);
|
||||
} else if ((asDict = value as IDictionary) != null) {
|
||||
SerializeObject(asDict);
|
||||
} else if (value is char) {
|
||||
SerializeString(new string((char) value, 1));
|
||||
} else {
|
||||
SerializeOther(value);
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeObject(IDictionary obj) {
|
||||
bool first = true;
|
||||
|
||||
builder.Append('{');
|
||||
|
||||
foreach (object e in obj.Keys) {
|
||||
if (!first) {
|
||||
builder.Append(',');
|
||||
}
|
||||
|
||||
SerializeString(e.ToString());
|
||||
builder.Append(':');
|
||||
|
||||
SerializeValue(obj[e]);
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builder.Append('}');
|
||||
}
|
||||
|
||||
void SerializeArray(IList anArray) {
|
||||
builder.Append('[');
|
||||
|
||||
bool first = true;
|
||||
|
||||
foreach (object obj in anArray) {
|
||||
if (!first) {
|
||||
builder.Append(',');
|
||||
}
|
||||
|
||||
SerializeValue(obj);
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builder.Append(']');
|
||||
}
|
||||
|
||||
void SerializeString(string str) {
|
||||
builder.Append('\"');
|
||||
|
||||
char[] charArray = str.ToCharArray();
|
||||
foreach (var c in charArray) {
|
||||
switch (c) {
|
||||
case '"':
|
||||
builder.Append("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
builder.Append("\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
builder.Append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
builder.Append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
builder.Append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.Append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
builder.Append("\\t");
|
||||
break;
|
||||
default:
|
||||
int codepoint = Convert.ToInt32(c);
|
||||
if ((codepoint >= 32) && (codepoint <= 126)) {
|
||||
builder.Append(c);
|
||||
} else {
|
||||
builder.Append("\\u");
|
||||
builder.Append(codepoint.ToString("x4"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append('\"');
|
||||
}
|
||||
|
||||
void SerializeOther(object value) {
|
||||
// NOTE: decimals lose precision during serialization.
|
||||
// They always have, I'm just letting you know.
|
||||
// Previously floats and doubles lost precision too.
|
||||
if (value is float) {
|
||||
builder.Append(((float) value).ToString("R"));
|
||||
} else if (value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is ulong) {
|
||||
builder.Append(value);
|
||||
} else if (value is double
|
||||
|| value is decimal) {
|
||||
builder.Append(Convert.ToDouble(value).ToString("R"));
|
||||
} else {
|
||||
SerializeString(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5f7a61f19ec6f294a8c26f6050e199dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23ccfd9225778c242b44692e9fa9540a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8e00bc6bd174cae4c869cf1b29186e43
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
using GCloud.UQM;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
public class CrashSightAnrMonitor
|
||||
{
|
||||
private static CrashSightMonoBehaviour monoBehaviour = CrashSightMonoBehaviour.Instance;
|
||||
private static int anrTimeoutMs = 5000;
|
||||
private static int detectionTimeoutMs = 1000;
|
||||
protected static bool Paused { get; private set; } = false;
|
||||
private static int ticksSinceUiUpdate = 0;
|
||||
private static bool reported = false;
|
||||
private static bool running = false;
|
||||
private static Thread thread;
|
||||
|
||||
public static void Start(int timeoutMs = 5000)
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
running = true;
|
||||
}
|
||||
anrTimeoutMs = timeoutMs;
|
||||
detectionTimeoutMs = Math.Max(1, anrTimeoutMs / 5);
|
||||
|
||||
monoBehaviour.ApplicationPausing += () => Paused = true;
|
||||
monoBehaviour.ApplicationResuming += () => Paused = false;
|
||||
monoBehaviour.ApplicationQuitting += () => Stop();
|
||||
|
||||
thread = new Thread(Run)
|
||||
{
|
||||
Name = "CrashSight-ANR-Monitor",
|
||||
IsBackground = true,
|
||||
Priority = System.Threading.ThreadPriority.BelowNormal,
|
||||
};
|
||||
thread.Start();
|
||||
|
||||
monoBehaviour.StartCoroutine(UpdateUiStatus());
|
||||
}
|
||||
public static void Stop()
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
|
||||
private static IEnumerator UpdateUiStatus()
|
||||
{
|
||||
UQMCrash.SetEngineMainThread();
|
||||
var waitForSeconds = new WaitForSecondsRealtime((float)detectionTimeoutMs / 1000);
|
||||
|
||||
yield return waitForSeconds;
|
||||
while (running)
|
||||
{
|
||||
ticksSinceUiUpdate = 0;
|
||||
reported = false;
|
||||
yield return waitForSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
ticksSinceUiUpdate += detectionTimeoutMs;
|
||||
Thread.Sleep(detectionTimeoutMs);
|
||||
|
||||
if (Paused)
|
||||
{
|
||||
ticksSinceUiUpdate = 0;
|
||||
}
|
||||
else if (ticksSinceUiUpdate >= anrTimeoutMs && !reported)
|
||||
{
|
||||
Report();
|
||||
reported = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UQMLog.LogError("CrashSightAnrMonitor meets an unknown error = \n" + ex.Message + "\n" + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Report()
|
||||
{
|
||||
string message = $"Application not responding for at least {anrTimeoutMs} ms.";
|
||||
UQMLog.Log(message);
|
||||
UQMCrash.ProcessEngineAnr(1);
|
||||
}
|
||||
}
|
||||
|
||||
public class UnityAnrException : Exception
|
||||
{
|
||||
internal UnityAnrException() : base() { }
|
||||
internal UnityAnrException(string message) : base(message) { }
|
||||
internal UnityAnrException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// ----------------------------------------
|
||||
//
|
||||
// CrashSightCallbackDelegate.cs
|
||||
//
|
||||
// Author:
|
||||
// Yeelik,
|
||||
//
|
||||
// Copyright (c) 2015 CrashSight. All rights reserved.
|
||||
//
|
||||
// ----------------------------------------
|
||||
//
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class CrashSightCallback
|
||||
{
|
||||
private static volatile bool isQuitting = false;
|
||||
private static object quitLocker = new object();
|
||||
|
||||
static CrashSightCallback()
|
||||
{
|
||||
// 注册应用退出事件监听器
|
||||
Application.quitting += OnApplicationQuitting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用退出时的回调
|
||||
/// </summary>
|
||||
private static void OnApplicationQuitting()
|
||||
{
|
||||
lock (quitLocker)
|
||||
{
|
||||
isQuitting = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查应用是否正在退出
|
||||
/// </summary>
|
||||
public static bool IsQuitting()
|
||||
{
|
||||
lock (quitLocker)
|
||||
{
|
||||
return isQuitting;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string OnCrashBaseRetEvent(int methodId, int crashType);
|
||||
|
||||
}
|
||||
|
||||
public abstract class CrashSightLogCallback
|
||||
{
|
||||
private static volatile bool isQuitting = false;
|
||||
private static object quitLocker = new object();
|
||||
|
||||
static CrashSightLogCallback()
|
||||
{
|
||||
// 注册应用退出事件监听器
|
||||
Application.quitting += OnApplicationQuitting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用退出时的回调
|
||||
/// </summary>
|
||||
private static void OnApplicationQuitting()
|
||||
{
|
||||
lock (quitLocker)
|
||||
{
|
||||
isQuitting = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查应用是否正在退出
|
||||
/// </summary>
|
||||
public static bool IsQuitting()
|
||||
{
|
||||
lock (quitLocker)
|
||||
{
|
||||
return isQuitting;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string OnSetLogPathEvent(int methodId, int crashType);
|
||||
|
||||
public abstract void OnLogUploadResultEvent(int methodId, int crashType, int result);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ba1b54454a2619141b38d419338ee9aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
[AddComponentMenu("")]
|
||||
public partial class CrashSightMonoBehaviour : MonoBehaviour
|
||||
{
|
||||
private static CrashSightMonoBehaviour _instance;
|
||||
public static CrashSightMonoBehaviour Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
var gameObject = new GameObject("CrashSightMonoBehaviour") { hideFlags = HideFlags.HideAndDontSave };
|
||||
DontDestroyOnLoad(gameObject);
|
||||
_instance = gameObject.AddComponent<CrashSightMonoBehaviour>();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action ApplicationResuming;
|
||||
|
||||
public event Action ApplicationPausing;
|
||||
|
||||
public event Action ApplicationQuitting;
|
||||
|
||||
internal bool _isRunning = true;
|
||||
|
||||
public void UpdatePauseStatus(bool paused)
|
||||
{
|
||||
if (paused && _isRunning)
|
||||
{
|
||||
_isRunning = false;
|
||||
ApplicationPausing?.Invoke();
|
||||
}
|
||||
else if (!paused && !_isRunning)
|
||||
{
|
||||
_isRunning = true;
|
||||
ApplicationResuming?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnApplicationPause(bool pauseStatus) => UpdatePauseStatus(pauseStatus);
|
||||
|
||||
internal void OnApplicationFocus(bool hasFocus) => UpdatePauseStatus(!hasFocus);
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
ApplicationQuitting?.Invoke();
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
using AOT;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
// 使用前请先打开ENABLE_CRASHSIGHT_STACKTRACE宏
|
||||
public class CrashSightStackTrace
|
||||
{
|
||||
public static bool enable = false;
|
||||
|
||||
//CrashSightStackTrace开关,仅在il2cpp编译时允许打开
|
||||
public static void setEnable(bool enable)
|
||||
{
|
||||
#if ENABLE_IL2CPP && ENABLE_CRASHSIGHT_STACKTRACE
|
||||
CrashSightStackTrace.enable = enable;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_ANDROID
|
||||
public const string lib = "il2cpp";
|
||||
#elif UNITY_IOS
|
||||
public const string lib = "__Internal";
|
||||
#endif
|
||||
|
||||
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR && ENABLE_IL2CPP && ENABLE_CRASHSIGHT_STACKTRACE
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void il2cpp_current_thread_walk_frame_stack(Il2CppFrameWalkFunc func, IntPtr data);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_method_get_name(IntPtr method);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int il2cpp_method_get_param_count(IntPtr method);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_method_get_class(IntPtr method);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_method_get_param(IntPtr method, int index);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_class_get_name(IntPtr klass);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_class_get_namespace(IntPtr klass);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_type_get_name(IntPtr type);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_class_get_declaring_type(IntPtr klass);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr il2cpp_class_from_il2cpp_type(IntPtr type);
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool il2cpp_type_is_byref(IntPtr type);
|
||||
#endif
|
||||
|
||||
//type结构体,用于直接读取指针指向的内容,能不用则不用,尽量使用il2cpp的API
|
||||
public struct Il2CppType
|
||||
{
|
||||
public IntPtr unionData;
|
||||
public Int16 attrs;
|
||||
public Byte type;
|
||||
public Byte num_mods;
|
||||
public bool byref()
|
||||
{
|
||||
return (num_mods & 64) != 0;//0b01000000
|
||||
}
|
||||
};
|
||||
|
||||
public delegate void Il2CppFrameWalkFunc(IntPtr info, IntPtr user_data);
|
||||
|
||||
//FrameWalk回调,每次处理一帧的信息
|
||||
[MonoPInvokeCallback(typeof(Il2CppFrameWalkFunc))]
|
||||
public static void Il2CppFrameWalkFuncImp(IntPtr info, IntPtr data)
|
||||
{
|
||||
string stackFrame = "";
|
||||
IntPtr method = (IntPtr)Marshal.PtrToStructure(info, typeof(IntPtr));
|
||||
string name = Marshal.PtrToStringAnsi(il2cpp_method_get_name(method));
|
||||
IntPtr klass = il2cpp_method_get_class(method);
|
||||
string klassName = Marshal.PtrToStringAnsi(il2cpp_class_get_name(klass));
|
||||
string klassNamespaze = Marshal.PtrToStringAnsi(il2cpp_class_get_namespace(klass));
|
||||
|
||||
//模板类等,额外执行命名空间查找
|
||||
if(string.IsNullOrEmpty(klassNamespaze))
|
||||
{
|
||||
IntPtr declaring_type = il2cpp_class_get_declaring_type(klass);
|
||||
if (declaring_type != IntPtr.Zero)
|
||||
{
|
||||
klassNamespaze = Marshal.PtrToStringAnsi(il2cpp_class_get_namespace(declaring_type));
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(klassNamespaze))
|
||||
stackFrame += klassNamespaze + ".";
|
||||
stackFrame += klassName + ":" + name + "(";
|
||||
|
||||
//遍历参数
|
||||
int paraCount = il2cpp_method_get_param_count(method);
|
||||
for (int i = 0; i < paraCount; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
stackFrame += ", ";
|
||||
}
|
||||
IntPtr type = il2cpp_method_get_param(method, i);
|
||||
IntPtr typeClass = il2cpp_class_from_il2cpp_type(type);
|
||||
string typeName = Marshal.PtrToStringAnsi(il2cpp_class_get_name(typeClass));
|
||||
stackFrame += typeName;
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
//il2cpp_type_is_byref可用时,直接使用它判断参数是否为引用
|
||||
bool byref = il2cpp_type_is_byref(type);
|
||||
if (byref)
|
||||
{
|
||||
stackFrame += "&";
|
||||
}
|
||||
#else
|
||||
//il2cpp_type_is_byref不可用时,只能通过指针访问结构(可能不安全)
|
||||
Il2CppType typeimpl = (Il2CppType)Marshal.PtrToStructure(type, typeof(Il2CppType));
|
||||
if (typeimpl.byref())
|
||||
{
|
||||
stackFrame += "&";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
stackFrame += ")\n";
|
||||
stackTrace = stackFrame + stackTrace;
|
||||
}
|
||||
#endif
|
||||
|
||||
static string stackTrace;
|
||||
|
||||
//stacktrace入口,默认使用StackTraceUtility.ExtractStackTrace(),需要setEnable来切换到CrashSightStackTrace
|
||||
public static string ExtractStackTrace()
|
||||
{
|
||||
if (!enable)
|
||||
{
|
||||
return StackTraceUtility.ExtractStackTrace();
|
||||
}
|
||||
stackTrace = string.Empty;
|
||||
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR && ENABLE_IL2CPP && ENABLE_CRASHSIGHT_STACKTRACE
|
||||
il2cpp_current_thread_walk_frame_stack(Il2CppFrameWalkFuncImp, new IntPtr());
|
||||
|
||||
//有些il2cpp版本会把il2cpp_current_thread_walk_frame_stack打出来,有些则不会,判断并丢弃
|
||||
int line1 = stackTrace.IndexOf('\n');
|
||||
int line2 = stackTrace.IndexOf('\n', line1 + 1);
|
||||
if (stackTrace.Substring(0, line1) == "CrashSightStackTrace:ExtractStackTrace()")
|
||||
{
|
||||
stackTrace = stackTrace.Substring(line1 + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
stackTrace = stackTrace.Substring(line2 + 1);
|
||||
}
|
||||
#endif
|
||||
return stackTrace;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 134a5ecbf5aa66d4d9214b3669828a24
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Define_list:
|
||||
- SDK_CRASHSIGHT
|
||||
|
|
@ -1 +1 @@
|
|||
0.0.1
|
||||
0.0.2
|
||||
Loading…
Reference in New Issue