| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080 | // ----------------------------------------////  BuglyAgent.cs////  Author://       Yeelik, <bugly@tencent.com>////  Copyright (c) 2015 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;// We dont use the LogType enum in Unity as the numerical order doesnt suit our purposes/// <summary>/// Log severity. /// { Log, LogDebug, LogInfo, LogWarning, LogAssert, LogError, LogException }/// </summary>public enum LogSeverity{    Log,    LogDebug,    LogInfo,    LogWarning,    LogAssert,    LogError,    LogException}/// <summary>/// Bugly agent./// </summary>public sealed class BuglyAgent{        // Define delegate support multicasting to replace the 'Application.LogCallback'    public delegate void LogCallbackDelegate (string condition,string stackTrace,LogType type);    /// <summary>    /// Configs the type of the crash reporter and customized log level to upload    /// </summary>    /// <param name="type">Type. Default=0, 1=Bugly v2.x MSDK=2</param>    /// <param name="logLevel">Log level. Off=0,Error=1,Warn=2,Info=3,Debug=4</param>    public static void ConfigCrashReporter(int type, int logLevel){        _SetCrashReporterType (type);        _SetCrashReporterLogLevel (logLevel);    }    /// <summary>    /// Init sdk with the specified appId.     /// <para>This will initialize sdk to report native exception such as obj-c, c/c++, java exceptions, and also enable c# exception handler to report c# exception logs</para>    /// </summary>    /// <param name="appId">App identifier.</param>    public static void InitWithAppId (string appId)    {        if (IsInitialized) {            DebugLog (null, "BuglyAgent has already been initialized.");                        return;        }                if (string.IsNullOrEmpty (appId)) {            return;        }                // init the sdk with app id        InitBuglyAgent (appId);        DebugLog (null, "Initialized with app id: {0}", appId);                // Register the LogCallbackHandler by Application.RegisterLogCallback(Application.LogCallback)        _RegisterExceptionHandler ();    }        /// <summary>    /// Only Enable the C# exception handler.     ///     /// <para>    /// You can call it when you do not call the 'InitWithAppId(string)', but you must make sure initialized the sdk in elsewhere,     /// such as the native code in associated Android or iOS project.    /// </para>    ///     /// <para>    /// Default Level is <c>LogError</c>, so the LogError, LogException will auto report.    /// </para>    ///     /// <para>    /// You can call the method <code>BuglyAgent.ConfigAutoReportLogLevel(LogSeverity)</code>    /// to change the level to auto report if you known what are you doing.    /// </para>    ///     /// </summary>    public static void EnableExceptionHandler ()    {        if (IsInitialized) {            DebugLog (null, "BuglyAgent has already been initialized.");            return;        }                DebugLog (null, "Only enable the exception handler, please make sure you has initialized the sdk in the native code in associated Android or iOS project.");                // Register the LogCallbackHandler by Application.RegisterLogCallback(Application.LogCallback)        _RegisterExceptionHandler ();    }        /// <summary>    /// Registers the log callback handler.     ///     /// If you need register logcallback using Application.RegisterLogCallback(LogCallback),    /// you can call this method to replace it.    ///     /// <para></para>    /// </summary>    /// <param name="handler">Handler.</param>    public static void RegisterLogCallback (LogCallbackDelegate handler)    {        if (handler != null) {            DebugLog (null, "Add log callback handler: {0}", handler);                        _LogCallbackEventHandler += handler;        }    }        /// <summary>    /// Sets the log callback extras handler.    /// </summary>    /// <param name="handler">Handler.</param>    public static void SetLogCallbackExtrasHandler(Func<Dictionary<string, string>> handler){        if (handler != null) {            _LogCallbackExtrasHandler = handler;                        DebugLog(null, "Add log callback extra data handler : {0}", handler);        }    }        /// <summary>    /// Reports the exception.    /// </summary>    /// <param name="e">E.</param>    /// <param name="message">Message.</param>    public static void ReportException (System.Exception e, string message)    {        if (!IsInitialized) {            return;        }                DebugLog (null, "Report exception: {0}\n------------\n{1}\n------------", message, e);                _HandleException (e, message, false);    }        /// <summary>    /// Reports the exception.    /// </summary>    /// <param name="name">Name.</param>    /// <param name="message">Message.</param>    /// <param name="stackTrace">Stack trace.</param>    public static void ReportException (string name, string message, string stackTrace)    {        if (!IsInitialized) {            return;        }                DebugLog (null, "Report exception: {0} {1} \n{2}", name, message, stackTrace);                _HandleException (LogSeverity.LogException, name, message, stackTrace, false);    }        /// <summary>    /// Unregisters the log callback.    /// </summary>    /// <param name="handler">Handler.</param>    public static void UnregisterLogCallback (LogCallbackDelegate handler)    {        if (handler != null) {            DebugLog (null, "Remove log callback handler");                        _LogCallbackEventHandler -= handler;        }    }        /// <summary>    /// Sets the user identifier.    /// </summary>    /// <param name="userId">User identifier.</param>    public static void SetUserId (string userId)    {        if (!IsInitialized) {            return;        }        DebugLog (null, "Set user id: {0}", userId);                SetUserInfo (userId);    }        /// <summary>    /// Sets the scene.    /// </summary>    /// <param name="sceneId">Scene identifier.</param>    public static void SetScene (int sceneId)    {        if (!IsInitialized) {            return;        }        DebugLog (null, "Set scene: {0}", sceneId);                SetCurrentScene (sceneId);    }        /// <summary>    /// Adds the scene data.    /// </summary>    /// <param name="key">Key.</param>    /// <param name="value">Value.</param>    public static void AddSceneData (string key, string value)    {        if (!IsInitialized) {            return;        }                DebugLog (null, "Add scene data: [{0}, {1}]", key, value);                AddKeyAndValueInScene (key, value);    }        /// <summary>    /// Configs the debug mode.    /// </summary>    /// <param name="enable">If set to <c>true</c> debug mode.</param>    public static void ConfigDebugMode (bool enable)    {        EnableDebugMode (enable);        DebugLog (null, "{0} the log message print to console", enable ? "Enable" : "Disable");    }        /// <summary>    /// Configs the auto quit application.    /// </summary>    /// <param name="autoQuit">If set to <c>true</c> auto quit.</param>    public static void ConfigAutoQuitApplication (bool autoQuit)    {        _autoQuitApplicationAfterReport = autoQuit;    }        /// <summary>    /// Configs the auto report log level. Default is LogSeverity.LogError.    /// <example>    /// LogSeverity { Log, LogDebug, LogInfo, LogWarning, LogAssert, LogError, LogException }    /// </example>    /// </summary>    ///     /// <param name="level">Level.</param>     public static void ConfigAutoReportLogLevel (LogSeverity level)    {        _autoReportLogLevel = level;    }        /// <summary>    /// Configs the default.    /// </summary>    /// <param name="channel">Channel.</param>    /// <param name="version">Version.</param>    /// <param name="user">User.</param>    /// <param name="delay">Delay.</param>    public static void ConfigDefault (string channel, string version, string user, long delay)    {        DebugLog (null, "Config default channel:{0}, version:{1}, user:{2}, delay:{3}", channel, version, user, delay);        ConfigDefaultBeforeInit (channel, version, user, delay);    }        /// <summary>    /// Logs the debug.    /// </summary>    /// <param name="tag">Tag.</param>    /// <param name="format">Format.</param>    /// <param name="args">Arguments.</param>    public static void DebugLog (string tag, string format, params object[] args)    {        if(!_debugMode) {            return;        }        if (string.IsNullOrEmpty (format)) {            return;        }                Console.WriteLine ("[BuglyAgent] <Debug> - {0} : {1}", tag, string.Format (format, args));    }        /// <summary>    /// Prints the log.    /// </summary>    /// <param name="level">Level.</param>    /// <param name="format">Format.</param>    /// <param name="args">Arguments.</param>    public static void PrintLog (LogSeverity level, string format, params object[] args)    {        if (string.IsNullOrEmpty (format)) {            return;        }                LogRecord (level, string.Format (format, args));    }        #if UNITY_EDITOR || UNITY_STANDALONE        #region Interface(Empty) in Editor     private static void InitBuglyAgent (string appId)    {    }        private static void ConfigDefaultBeforeInit(string channel, string version, string user, long delay){    }        private static void EnableDebugMode(bool enable){    }        private static void SetUserInfo(string userInfo){    }        private static void ReportException (int type,string name, string message, string stackTrace, bool quitProgram)    {    }        private static void SetCurrentScene(int sceneId) {    }        private static void AddKeyAndValueInScene(string key, string value){    }        private static void AddExtraDataWithException(string key, string value) {        // only impl for iOS    }        private static void LogRecord(LogSeverity level, string message){    }        private static void SetUnityVersion(){            }    #endregion        #elif UNITY_ANDROID    //  #if UNITY_ANDROID        #region Interface for Android    private static readonly string GAME_AGENT_CLASS = "com.tencent.bugly.agent.GameAgent";    private static readonly int TYPE_U3D_CRASH = 4;    private static readonly int GAME_TYPE_UNITY = 2;    private static bool hasSetGameType = false;    private static AndroidJavaClass _gameAgentClass = null;        public static AndroidJavaClass GameAgent {        get {            if (_gameAgentClass == null) {                _gameAgentClass = new AndroidJavaClass(GAME_AGENT_CLASS);//                using (AndroidJavaClass clazz = new AndroidJavaClass(CLASS_UNITYAGENT)) {//                    _gameAgentClass = clazz.CallStatic<AndroidJavaObject> ("getInstance");//                }            }            if (!hasSetGameType) {                // set game type: unity(2).                _gameAgentClass.CallStatic ("setGameType", GAME_TYPE_UNITY);                hasSetGameType = true;            }            return _gameAgentClass;        }    }        private static string _configChannel;    private static string _configVersion;    private static string _configUser;    private static long _configDelayTime;        private static void ConfigDefaultBeforeInit(string channel, string version, string user, long delay){        _configChannel = channel;        _configVersion = version;        _configUser = user;        _configDelayTime = delay;    }    private static bool _configCrashReporterPackage = false;        private static void ConfigCrashReporterPackage(){                if (!_configCrashReporterPackage) {            try {                GameAgent.CallStatic("setSdkPackageName", _crashReporterPackage);                _configCrashReporterPackage = true;            } catch {                            }        }            }    private static void InitBuglyAgent(string appId)    {        if (IsInitialized) {            return;        }                ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("initCrashReport", appId, _configChannel, _configVersion, _configUser, _configDelayTime);            _isInitialized = true;        } catch {                    }    }        private static void EnableDebugMode(bool enable){        _debugMode = enable;        ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("setLogEnable", enable);        } catch {                    }    }        private static void SetUserInfo(string userInfo){        ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("setUserId", userInfo);        } catch {        }    }        private static void ReportException (int type, string name, string reason, string stackTrace, bool quitProgram)    {        ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("postException", TYPE_U3D_CRASH, name, reason, stackTrace, quitProgram);        } catch {                    }    }        private static void SetCurrentScene(int sceneId) {        ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("setUserSceneTag", sceneId);        } catch {                    }    }        private static void SetUnityVersion(){        ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("setSdkConfig", "UnityVersion", Application.unityVersion);        } catch {                    }    }        private static void AddKeyAndValueInScene(string key, string value){        ConfigCrashReporterPackage();        try {            GameAgent.CallStatic("putUserData", key, value);        } catch {                    }    }        private static void AddExtraDataWithException(string key, string value) {        // no impl    }        private static void LogRecord(LogSeverity level, string message){        if (level < LogSeverity.LogWarning) {            DebugLog (level.ToString (), message);        }        ConfigCrashReporterPackage();                try {            GameAgent.CallStatic("printLog", string.Format ("<{0}> - {1}", level.ToString (), message));        } catch {                    }    }        #endregion        #elif UNITY_IPHONE || UNITY_IOS        #region Interface for iOS        private static bool _crashReporterTypeConfiged = false;    private static void ConfigCrashReporterType(){        if (!_crashReporterTypeConfiged) {            try {                _BuglyConfigCrashReporterType(_crashReporterType);                _crashReporterTypeConfiged = true;             } catch {                            }        }    }    private static void ConfigDefaultBeforeInit(string channel, string version, string user, long delay){        ConfigCrashReporterType();                try {            _BuglyDefaultConfig(channel, version, user, null);        } catch {                    }    }        private static void EnableDebugMode(bool enable){        _debugMode = enable;    }        private static void InitBuglyAgent (string appId)    {        ConfigCrashReporterType();                if(!string.IsNullOrEmpty(appId)) {                        _BuglyInit(appId, _debugMode, _crashReproterCustomizedLogLevel); // Log level         }    }        private static void SetUnityVersion(){        ConfigCrashReporterType();                _BuglySetExtraConfig("UnityVersion", Application.unityVersion);    }        private static void SetUserInfo(string userInfo){        if(!string.IsNullOrEmpty(userInfo)) {            ConfigCrashReporterType();                        _BuglySetUserId(userInfo);        }    }        private static void ReportException (int type, string name, string reason, string stackTrace, bool quitProgram)    {        ConfigCrashReporterType();                string extraInfo = "";        Dictionary<string, string> extras = null;        if (_LogCallbackExtrasHandler != null) {            extras = _LogCallbackExtrasHandler();        }        if (extras == null || extras.Count == 0) {            extras = new Dictionary<string, string> ();            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<string,string> 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 SetCurrentScene(int sceneId) {        ConfigCrashReporterType();                _BuglySetTag(sceneId);    }        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){        if (level < LogSeverity.LogWarning) {            DebugLog (level.ToString (), 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;    }        // --- dllimport start ---    [DllImport("__Internal")]    private static extern void _BuglyInit(string appId, bool debug, int level);        [DllImport("__Internal")]    private static extern void _BuglySetUserId(string userId);        [DllImport("__Internal")]    private static extern void _BuglySetTag(int tag);        [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 end    #endregion        #endif        #region Privated Fields and Methods     private static event LogCallbackDelegate _LogCallbackEventHandler;        private static bool _isInitialized = false;    private static LogSeverity _autoReportLogLevel = LogSeverity.LogError;    private static int _crashReporterType = 1;  // Default=0,1=Bugly-V2,MSDKBugly=2, IMSDKBugly=3#if UNITY_ANDROID    // The crash reporter package name, default is 'com.tencent.bugly'    private static string _crashReporterPackage = "com.tencent.bugly";#endif#if UNITY_IPHONE || UNITY_IOS    private static int _crashReproterCustomizedLogLevel = 2; // Off=0,Error=1,Warn=2,Info=3,Debug=4#endif    #pragma warning disable 414    private static bool _debugMode = false;    private static bool _autoQuitApplicationAfterReport = false;        private static readonly int EXCEPTION_TYPE_UNCAUGHT = 1;    private static readonly int EXCEPTION_TYPE_CAUGHT = 2;    private static readonly string _pluginVersion = "1.5.1";        private static Func<Dictionary<string, string>> _LogCallbackExtrasHandler;        public static string PluginVersion {        get { return _pluginVersion; }    }        public static bool IsInitialized {        get { return _isInitialized; }    }        public static bool AutoQuitApplicationAfterReport {        get { return _autoQuitApplicationAfterReport; }    }    private static void _SetCrashReporterType(int type){        _crashReporterType = type;        if (_crashReporterType == 2) {#if UNITY_ANDROID            _crashReporterPackage = "com.tencent.bugly.msdk";#endif        }    }    private static void _SetCrashReporterLogLevel(int logLevel){#if UNITY_IPHONE || UNITY_IOS        _crashReproterCustomizedLogLevel = logLevel;#endif    }    private static void _RegisterExceptionHandler ()    {        try {            // hold only one instance                         #if UNITY_5_3_OR_NEWER            Application.logMessageReceived += _OnLogCallbackHandler;            #else            Application.RegisterLogCallback (_OnLogCallbackHandler);            #endif            AppDomain.CurrentDomain.UnhandledException += _OnUncaughtExceptionHandler;                        _isInitialized = true;                        DebugLog (null, "Register the log callback in Unity {0}", Application.unityVersion);        } catch {                    }                SetUnityVersion ();    }        private static void _UnregisterExceptionHandler ()    {        try {            #if UNITY_5_3_OR_NEWER            Application.logMessageReceived -= _OnLogCallbackHandler;            #else            Application.RegisterLogCallback (null);            #endif            System.AppDomain.CurrentDomain.UnhandledException -= _OnUncaughtExceptionHandler;            DebugLog (null, "Unregister the log callback in unity {0}", Application.unityVersion);        } catch {                    }    }        private static void _OnLogCallbackHandler (string condition, string stackTrace, LogType type)    {        if (_LogCallbackEventHandler != null) {            _LogCallbackEventHandler (condition, stackTrace, type);        }                if (!IsInitialized) {            return;        }                if (!string.IsNullOrEmpty (condition) && condition.Contains ("[BuglyAgent] <Log>")) {            return;        }                if (_uncaughtAutoReportOnce) {            return;        }                // convert the log level        LogSeverity logLevel = LogSeverity.Log;        switch (type) {        case LogType.Exception:            logLevel = LogSeverity.LogException;            break;        case LogType.Error:            logLevel = LogSeverity.LogError;            break;        case LogType.Assert:            logLevel = LogSeverity.LogAssert;            break;        case LogType.Warning:            logLevel = LogSeverity.LogWarning;            break;        case LogType.Log:            logLevel = LogSeverity.LogDebug;            break;        default:            break;        }                if (LogSeverity.Log == logLevel) {            return;        }                _HandleException (logLevel, null, condition, stackTrace, true);    }        private static void _OnUncaughtExceptionHandler (object sender, System.UnhandledExceptionEventArgs args)    {        if (args == null || args.ExceptionObject == null) {            return;        }                try {            if (args.ExceptionObject.GetType () != typeof(System.Exception)) {                return;            }        } catch {            if (UnityEngine.Debug.isDebugBuild == true) {                UnityEngine.Debug.Log ("BuglyAgent: Failed to report uncaught exception");            }                        return;        }                if (!IsInitialized) {            return;        }                if (_uncaughtAutoReportOnce) {            return;        }                _HandleException ((System.Exception)args.ExceptionObject, null, true);    }        private static void _HandleException (System.Exception e, string message, bool uncaught)    {        if (e == null) {            return;        }                if (!IsInitialized) {            return;        }                string name = e.GetType ().Name;        string reason = e.Message;                if (!string.IsNullOrEmpty (message)) {            reason = string.Format ("{0}{1}***{2}", reason, Environment.NewLine, message);        }                StringBuilder stackTraceBuilder = new StringBuilder ("");                StackTrace stackTrace = new StackTrace (e, true);        int count = stackTrace.FrameCount;        for (int i = 0; i < count; i++) {            StackFrame frame = stackTrace.GetFrame (i);                        stackTraceBuilder.AppendFormat ("{0}.{1}", frame.GetMethod ().DeclaringType.Name, frame.GetMethod ().Name);                        ParameterInfo[] parameters = frame.GetMethod ().GetParameters ();            if (parameters == null || parameters.Length == 0) {                stackTraceBuilder.Append (" () ");            } else {                stackTraceBuilder.Append (" (");                                int pcount = parameters.Length;                                ParameterInfo param = null;                for (int p = 0; p < pcount; p++) {                    param = parameters [p];                    stackTraceBuilder.AppendFormat ("{0} {1}", param.ParameterType.Name, param.Name);                                        if (p != pcount - 1) {                        stackTraceBuilder.Append (", ");                    }                }                param = null;                                stackTraceBuilder.Append (") ");            }                        string fileName = frame.GetFileName ();            if (!string.IsNullOrEmpty (fileName) && !fileName.ToLower ().Equals ("unknown")) {                fileName = fileName.Replace ("\\", "/");                                int loc = fileName.ToLower ().IndexOf ("/assets/");                if (loc < 0) {                    loc = fileName.ToLower ().IndexOf ("assets/");                }                                if (loc > 0) {                    fileName = fileName.Substring (loc);                }                                stackTraceBuilder.AppendFormat ("(at {0}:{1})", fileName, frame.GetFileLineNumber ());            }            stackTraceBuilder.AppendLine ();        }                // report        _reportException (uncaught, name, reason, stackTraceBuilder.ToString ());    }        private static void _reportException (bool uncaught, string name, string reason, string stackTrace)    {        if (string.IsNullOrEmpty (name)) {            return;        }                if (string.IsNullOrEmpty (stackTrace)) {            stackTrace = StackTraceUtility.ExtractStackTrace ();        }                if (string.IsNullOrEmpty (stackTrace)) {            stackTrace = "Empty";                   } else {                        try {                string[] frames = stackTrace.Split ('\n');                                if (frames != null && frames.Length > 0) {                                        StringBuilder trimFrameBuilder = new StringBuilder ();                                        string frame = null;                    int count = frames.Length;                    for (int i = 0; i < count; i++) {                        frame = frames [i];                                                if (string.IsNullOrEmpty (frame) || string.IsNullOrEmpty (frame.Trim ())) {                            continue;                        }                                                frame = frame.Trim ();                                                // System.Collections.Generic                        if (frame.StartsWith ("System.Collections.Generic.") || frame.StartsWith ("ShimEnumerator")) {                            continue;                        }                        if (frame.StartsWith ("Bugly")) {                            continue;                        }                        if (frame.Contains ("..ctor")) {                            continue;                        }                                                int start = frame.ToLower ().IndexOf ("(at");                        int end = frame.ToLower ().IndexOf ("/assets/");                                                if (start > 0 && end > 0) {                            trimFrameBuilder.AppendFormat ("{0}(at {1}", frame.Substring (0, start).Replace (":", "."), frame.Substring (end));                        } else {                            trimFrameBuilder.Append (frame.Replace (":", "."));                        }                                                trimFrameBuilder.AppendLine ();                    }                                        stackTrace = trimFrameBuilder.ToString ();                }            } catch {                PrintLog(LogSeverity.LogWarning,"{0}", "Error to parse the stack trace");            }                    }                PrintLog (LogSeverity.LogError, "ReportException: {0} {1}\n*********\n{2}\n*********", name, reason, stackTrace);                _uncaughtAutoReportOnce = uncaught && _autoQuitApplicationAfterReport;                ReportException (uncaught ? EXCEPTION_TYPE_UNCAUGHT : EXCEPTION_TYPE_CAUGHT, name, reason, stackTrace, uncaught && _autoQuitApplicationAfterReport);    }        private static void _HandleException (LogSeverity logLevel, string name, string message, string stackTrace, bool uncaught)    {        if (!IsInitialized) {            DebugLog (null, "It has not been initialized.");            return;        }                if (logLevel == LogSeverity.Log) {            return;        }                if ((uncaught && logLevel < _autoReportLogLevel)) {            DebugLog (null, "Not report exception for level {0}", logLevel.ToString ());            return;        }                string type = null;        string reason = null;                if (!string.IsNullOrEmpty (message)) {            try {                if ((LogSeverity.LogException == logLevel) && message.Contains ("Exception")) {                                        Match match = new Regex (@"^(?<errorType>\S+):\s*(?<errorMessage>.*)", RegexOptions.Singleline).Match (message);                                        if (match.Success) {                        type = match.Groups ["errorType"].Value.Trim();                        reason = match.Groups ["errorMessage"].Value.Trim ();                    }                } else if ((LogSeverity.LogError == logLevel) && message.StartsWith ("Unhandled Exception:")) {                                        Match match = new Regex (@"^Unhandled\s+Exception:\s*(?<exceptionName>\S+):\s*(?<exceptionDetail>.*)", RegexOptions.Singleline).Match(message);                                        if (match.Success) {                        string exceptionName = match.Groups ["exceptionName"].Value.Trim();                        string exceptionDetail = match.Groups ["exceptionDetail"].Value.Trim ();                                                //                         int dotLocation = exceptionName.LastIndexOf(".");                        if (dotLocation > 0 && dotLocation != exceptionName.Length) {                            type = exceptionName.Substring(dotLocation + 1);                        } else {                            type = exceptionName;                        }                                                int stackLocation = exceptionDetail.IndexOf(" at ");                        if (stackLocation > 0) {                            //                             reason = exceptionDetail.Substring(0, stackLocation);                            // substring after " at "                            string callStacks = exceptionDetail.Substring(stackLocation + 3).Replace(" at ", "\n").Replace("in <filename unknown>:0","").Replace("[0x00000]","");                            //                            stackTrace = string.Format("{0}\n{1}", stackTrace, callStacks.Trim());                                                    } else {                            reason = exceptionDetail;                        }                                                // for LuaScriptException                        if(type.Equals("LuaScriptException") && exceptionDetail.Contains(".lua") && exceptionDetail.Contains("stack traceback:")) {                            stackLocation = exceptionDetail.IndexOf("stack traceback:");                            if(stackLocation > 0) {                                reason = exceptionDetail.Substring(0, stackLocation);                                // substring after "stack traceback:"                                string callStacks = exceptionDetail.Substring(stackLocation + 16).Replace(" [", " \n[");                                                                //                                stackTrace = string.Format("{0}\n{1}", stackTrace, callStacks.Trim());                            }                        }                    }                                    }            } catch {                            }                        if (string.IsNullOrEmpty (reason)) {                reason = message;            }        }                if (string.IsNullOrEmpty (name)) {            if (string.IsNullOrEmpty (type)) {                type = string.Format ("Unity{0}", logLevel.ToString ());            }        } else {            type = name;        }                _reportException (uncaught, type, reason, stackTrace);    }        private static bool _uncaughtAutoReportOnce = false;        #endregion    }
 |