// ---------------------------------------- // // BuglyCommon.cs // // Author: // bugly, // // Copyright (c) 2023 Bugly, Tencent. All rights reserved. // // ---------------------------------------- // using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Runtime.InteropServices; using AOT; public class BuglyCommon { private static int _crashReporterType = 1; // Default=0,1=Bugly-V2,MSDKBugly=2, IMSDKBugly=3 private static bool _debugMode = false; private static Func> _LogCallbackExtrasHandler; #if UNITY_ANDROID // Log Level private static int _crashReproterLogLevel = 0; // OFF=0, ERROR=1, WARN=2, INFO=3, DEBUG=4, VERBOS=5 public static int BuglyCrashReporterLogLevel { get { return _crashReproterLogLevel; } set { _crashReproterLogLevel = value; } } // The Bugly Performance Plugin List, Empty means Open Crash Only private static string[] _pluginArray = {}; #elif UNITY_IPHONE || UNITY_IOS private static int _crashReproterCustomizedLogLevel = 2; // Off=0,Error=1,Warn=2,Info=3,Debug=4 public static int BuglyReproterCustomizedLogLevel { get { return _crashReproterCustomizedLogLevel;} set { _crashReproterCustomizedLogLevel = value;} } // The Bugly Plugin List, default mode is Open Crash Only private static string[] _pluginArray = {"BuglyCrashMonitorPlugin", "RMMemoryMonitorPlugin"}; #endif public static string[] BuglyPluginArray { get { return _pluginArray;} set { _pluginArray = value;} } public static void InitBuglyAgent(string appId, string appKey) { InitBuglySDK(appId, appKey); } public static void SetBuglyUserId(string userId) { SetUserId(userId); } public static void SetBuglyDeviceId(string deviceId) { SetDeviceId(deviceId); } public static void SetBuglyAdditionalAttachmentPaths(string[] pathArray) { SetAdditionalAttachmentPaths(pathArray); } public static void SetBuglyCrashHandlerListener(BuglyCallback.ListenerAdapter listener) { SetCrashHandlerListener(listener); } public static void AddBuglyKeyAndValueInScene(string key, string value) { AddKeyAndValueInScene(key, value); } public static void ConfigBuglyDefaultBeforeInit (string channel, string version, string buildNum, string user, string model) { ConfigDefaultBeforeInit (channel, version, buildNum, user, model); } public static void LogBuglyRecord(LogSeverity level, string format, params object[] args) { LogRecord (level, string.Format (format, args)); } public static void SetSDKUnityVersion(){ SetUnityVersion(); } public static void ReportBuglyException (int type, string name, string reason, string stackTrace, bool quitProgram) { ReportException(type, name, reason, stackTrace, quitProgram); } public static void SetBuglyReporterType(int type){ _crashReporterType = type; } public static bool BuglyDebugMode { get { return _debugMode;} set { _debugMode = value;} } public static Func> BuglyLogCallbackExtrasHandler { get { return _LogCallbackExtrasHandler;} set { _LogCallbackExtrasHandler = value;} } public static void BuglySetLogLevel(int logLevel) { SetLogLevel(logLevel); } public static void BuglyStartInspectLeakObj(AndroidJavaObject javaObject) { StartInspectLeakObj(javaObject); } public static void BuglyLaunchAddTag(string tag) { LaunchAddTag(tag); } public static void BuglyLaunchSpanStart(string spanName, string parentSpanName) { LaunchSpanStart(spanName, parentSpanName); } public static void BuglyLaunchSpanEnd(string spanName) { LaunchSpanEnd(spanName); } public static void BuglyReportAppFullLaunch() { // launch end ReportAppFullLaunch(); } #if UNITY_ANDROID #region Interface for Android private static bool _isInit = false; // fetch java class private const string GAME_AGENT_CLASS = "com.tencent.bugly.agent.GameAgentPro"; private const int TYPE_U_3D_CRASH = 4; private const int GAME_TYPE_UNITY = 2; private static bool _hasSetGameType = false; private static AndroidJavaClass _gameAgentClass = null; // init set private static string _appVersion = ""; private static string _buildNum = ""; private static string _uniqueId = ""; private static string _userId = ""; private static string _deviceModel = ""; private static string _appVersionType = "Unknown"; private static string _appChannel = ""; private static int _logLevel = 0; private static AndroidJavaClass gameAgent { get { _gameAgentClass ??= new AndroidJavaClass(GAME_AGENT_CLASS); if (_hasSetGameType) return _gameAgentClass; _gameAgentClass.CallStatic ("setGameType", GAME_TYPE_UNITY); _hasSetGameType = true; return _gameAgentClass; } } // init private static void InitBuglySDK(string appId, string appKey) { try { if (_isInit) { UnityEngine.Debug.Log("Bugly has init, return."); return; } gameAgent.CallStatic("initAgent", appId, appKey, _appVersion, _buildNum, _uniqueId, _userId, _deviceModel, _appVersionType, _appChannel, BuglyDebugMode, _logLevel, BuglyPluginArray); _isInit = true; UnityEngine.Debug.Log("Bugly init success"); } catch(Exception ex){ UnityEngine.Debug.Log("Bugly init failed"); UnityEngine.Debug.Log(ex.ToString()); } } private static void SetUserId(string userId) { try { _userId = userId; if (_isInit) { gameAgent.CallStatic("updateUserIdAgent", userId); } } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void SetDeviceId(string deviceId) { try { _uniqueId = deviceId; if (_isInit) { gameAgent.CallStatic("updateUniqueIdAgent", deviceId); } } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void SetAdditionalAttachmentPaths(string[] pathArray){ try { gameAgent.CallStatic("setAdditionalAttachmentPathsAgent", pathArray); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void SetCrashHandlerListener(BuglyCallback.ListenerAdapter listener) { try { gameAgent.CallStatic("setCrashHandlerListenerAgent", listener); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void AddKeyAndValueInScene(string key, string value){ try { gameAgent.CallStatic("putUserDataAgent", key, value); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void ConfigDefaultBeforeInit(string channel, string version, string buildNum, string user, string model) { _appChannel = channel; _appVersion = version; _buildNum = buildNum; _userId = user; _deviceModel = model; } private static void LogRecord(LogSeverity level, string message) { // no impl } private static void SetUnityVersion() { // for special scene, no impl } private static void ReportException(int type, string errorName, string errorMsg, string stackTrace, bool quitProgram) { try { gameAgent.CallStatic("postExceptionAgent", TYPE_U_3D_CRASH, errorName, errorMsg, stackTrace, quitProgram); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void SetLogLevel(int logLevel) { try { gameAgent.CallStatic("updateLogLevelAgent", logLevel); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } // java memory leak private static void StartInspectLeakObj(AndroidJavaObject javaObject) { try { gameAgent.CallStatic("startInspectLeakObjAgent", javaObject); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } // launch private static void LaunchAddTag(string tag) { try { gameAgent.CallStatic("launchAddTagAgent", tag); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void LaunchSpanStart(string spanName, string parentSpanName) { try { gameAgent.CallStatic("launchSpanStartAgent", spanName, parentSpanName); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void LaunchSpanEnd(string spanName) { try { gameAgent.CallStatic("launchSpanEndAgent", spanName); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } private static void ReportAppFullLaunch() { try { gameAgent.CallStatic("reportAppFullLaunchAgent"); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); } } #endregion #elif UNITY_IPHONE || UNITY_IOS #region Interface for iOS private static bool _crashReporterTypeConfiged = false; private delegate string OnBuglyCrashCallback(string name, string reason, string user_info); private static BuglyCallback.ListenerAdapter _listener = null; [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)] private static extern void _BuglySetUnityCallback(OnBuglyCrashCallback callbackHandler); private static void ConfigCrashReporterType(){ if (!_crashReporterTypeConfiged) { try { _BuglyConfigCrashReporterType(_crashReporterType); _crashReporterTypeConfiged = true; } catch { } } } public static void ConfigDefaultBeforeInit(string channel, string version, string buildNum, string user, string model){ ConfigCrashReporterType(); try { _BuglyDefaultConfig(channel, version, user, null); } catch { } } private static void EnableDebugMode(bool enable){ _debugMode = enable; } private static void InitBuglySDK (string appId, string appKey) { ConfigCrashReporterType(); if(!string.IsNullOrEmpty(appId) && !string.IsNullOrEmpty(appKey)) { int count = _pluginArray.Length; IntPtr ptr = Marshal.AllocHGlobal(count * IntPtr.Size); for (int i = 0; i < count; i++) { IntPtr strPtr = Marshal.StringToHGlobalAnsi(_pluginArray[i]); Marshal.WriteIntPtr(ptr, i * IntPtr.Size, strPtr); } _BuglySetPluginArray(ptr, count); for (int i = 0; i < count; i++) { IntPtr strPtr = Marshal.ReadIntPtr(ptr, i * IntPtr.Size); Marshal.FreeHGlobal(strPtr); } Marshal.FreeHGlobal(ptr); _BuglyInit(appId, appKey, _debugMode, _crashReproterCustomizedLogLevel); // Log level } } private static void SetUnityVersion(){ ConfigCrashReporterType(); _BuglySetExtraConfig("UnityVersion", Application.unityVersion); } private static void SetUserId(string userid){ if(!string.IsNullOrEmpty(userid)) { ConfigCrashReporterType(); _BuglySetUserId(userid); } } private static void SetDeviceId(string deviceInfo){ if(!string.IsNullOrEmpty(deviceInfo)) { ConfigCrashReporterType(); _BuglySetDeviceId(deviceInfo); } } private static void SetDumpFilePath(string path){ } private static void ReportException (int type, string name, string reason, string stackTrace, bool quitProgram) { ConfigCrashReporterType(); string extraInfo = ""; Dictionary extras = null; if (_LogCallbackExtrasHandler != null) { extras = _LogCallbackExtrasHandler(); } if (extras == null || extras.Count == 0) { extras = new Dictionary (); extras.Add ("UnityVersion", Application.unityVersion); } if (extras != null && extras.Count > 0) { if (!extras.ContainsKey("UnityVersion")) { extras.Add ("UnityVersion", Application.unityVersion); } StringBuilder builder = new StringBuilder(); foreach(KeyValuePair kvp in extras){ builder.Append(string.Format("\"{0}\" : \"{1}\"", kvp.Key, kvp.Value)).Append(" , "); } extraInfo = string.Format("{{ {0} }}", builder.ToString().TrimEnd(" , ".ToCharArray())); } // 4 is C# exception _BuglyReportException(4, name, reason, stackTrace, extraInfo, quitProgram); } private static void AddKeyAndValueInScene(string key, string value){ ConfigCrashReporterType(); _BuglySetKeyValue(key, value); } private static void AddExtraDataWithException(string key, string value) { } private static void LogRecord(LogSeverity level, string message){ ConfigCrashReporterType(); _BuglyLogMessage(LogSeverityToInt(level), null, message); } private static int LogSeverityToInt(LogSeverity logLevel){ int level = 5; switch(logLevel) { case LogSeverity.Log: level = 5; break; case LogSeverity.LogDebug: level = 4; break; case LogSeverity.LogInfo: level = 3; break; case LogSeverity.LogWarning: case LogSeverity.LogAssert: level = 2; break; case LogSeverity.LogError: case LogSeverity.LogException: level = 1; break; default: level = 0; break; } return level; } private static void SetLogLevel(int logLevel) { } private static void StartInspectLeakObj(AndroidJavaObject javaObject) { // no impl for iOS } // launch private static void LaunchAddTag(string tag) { } private static void LaunchSpanStart(string spanName, string parentSpanName) { } private static void LaunchSpanEnd(string spanName) { } private static void ReportAppFullLaunch() { } [MonoPInvokeCallback(typeof(OnBuglyCrashCallback))] public static string OnBuglyCrashCallbackFunc(string name, string reason, string user_info) { if(_listener != null){ return _listener.OnBuglyCrashCallback(name, reason, user_info); } return "empty string"; } private static void SetCrashHandlerListener(BuglyCallback.ListenerAdapter listener) { if(listener != null){ _listener = listener; _BuglySetUnityCallback(OnBuglyCrashCallbackFunc); } } private static void SetAdditionalAttachmentPaths(string[] pathArray){ if (pathArray != null && pathArray.Length > 0){ int count = pathArray.Length; IntPtr ptr = Marshal.AllocHGlobal(count * IntPtr.Size); for (int i = 0; i < count; i++) { IntPtr strPtr = Marshal.StringToHGlobalAnsi(pathArray[i]); Marshal.WriteIntPtr(ptr, i * IntPtr.Size, strPtr); } _BuglySetAdditionalAttachmentPaths(ptr, count); for (int i = 0; i < count; i++) { IntPtr strPtr = Marshal.ReadIntPtr(ptr, i * IntPtr.Size); Marshal.FreeHGlobal(strPtr); } Marshal.FreeHGlobal(ptr); } } // --- dllimport start --- [DllImport("__Internal")] private static extern void _BuglyInit(string appId, string appKey, bool debug, int level); [DllImport("__Internal")] private static extern void _BuglySetUserId(string userId); [DllImport("__Internal")] private static extern void _BuglySetDeviceId(string deviceId); [DllImport("__Internal")] private static extern void _BuglySetKeyValue(string key, string value); [DllImport("__Internal")] private static extern void _BuglyReportException(int type, string name, string reason, string stackTrace, string extras, bool quit); [DllImport("__Internal")] private static extern void _BuglyDefaultConfig(string channel, string version, string user, string deviceId); [DllImport("__Internal")] private static extern void _BuglyLogMessage(int level, string tag, string log); [DllImport("__Internal")] private static extern void _BuglyConfigCrashReporterType(int type); [DllImport("__Internal")] private static extern void _BuglySetExtraConfig(string key, string value); [DllImport("__Internal")] private static extern void _BuglySetAdditionalAttachmentPaths(IntPtr pathArray, int count); [DllImport("__Internal")] private static extern void _BuglySetPluginArray(IntPtr pluginArray, int count); // dllimport end #endregion #endif }