源战役客户端
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

1082 linhas
34 KiB

  1. // ----------------------------------------
  2. //
  3. // BuglyAgent.cs
  4. //
  5. // Author:
  6. // Yeelik, <bugly@tencent.com>
  7. //
  8. // Copyright (c) 2015 Bugly, Tencent. All rights reserved.
  9. //
  10. // ----------------------------------------
  11. //
  12. using UnityEngine;
  13. using System;
  14. using System.Collections;
  15. using System.Collections.Generic;
  16. using System.Diagnostics;
  17. using System.Reflection;
  18. using System.Text;
  19. using System.Text.RegularExpressions;
  20. using System.Runtime.InteropServices;
  21. // We dont use the LogType enum in Unity as the numerical order doesnt suit our purposes
  22. /// <summary>
  23. /// Log severity.
  24. /// { Log, LogDebug, LogInfo, LogWarning, LogAssert, LogError, LogException }
  25. /// </summary>
  26. public enum LogSeverity
  27. {
  28. Log,
  29. LogDebug,
  30. LogInfo,
  31. LogWarning,
  32. LogAssert,
  33. LogError,
  34. LogException
  35. }
  36. /// <summary>
  37. /// Bugly agent.
  38. /// </summary>
  39. public sealed class BuglyAgent
  40. {
  41. // Define delegate support multicasting to replace the 'Application.LogCallback'
  42. public delegate void LogCallbackDelegate (string condition,string stackTrace,LogType type);
  43. /// <summary>
  44. /// Configs the type of the crash reporter and customized log level to upload
  45. /// </summary>
  46. /// <param name="type">Type. Default=0, 1=Bugly v2.x MSDK=2</param>
  47. /// <param name="logLevel">Log level. Off=0,Error=1,Warn=2,Info=3,Debug=4</param>
  48. public static void ConfigCrashReporter(int type, int logLevel){
  49. _SetCrashReporterType (type);
  50. _SetCrashReporterLogLevel (logLevel);
  51. }
  52. /// <summary>
  53. /// Init sdk with the specified appId.
  54. /// <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>
  55. /// </summary>
  56. /// <param name="appId">App identifier.</param>
  57. public static void InitWithAppId (string appId)
  58. {
  59. if (IsInitialized) {
  60. DebugLog (null, "BuglyAgent has already been initialized.");
  61. return;
  62. }
  63. if (string.IsNullOrEmpty (appId)) {
  64. return;
  65. }
  66. // init the sdk with app id
  67. InitBuglyAgent (appId);
  68. DebugLog (null, "Initialized with app id: {0}", appId);
  69. // Register the LogCallbackHandler by Application.RegisterLogCallback(Application.LogCallback)
  70. _RegisterExceptionHandler ();
  71. }
  72. /// <summary>
  73. /// Only Enable the C# exception handler.
  74. ///
  75. /// <para>
  76. /// You can call it when you do not call the 'InitWithAppId(string)', but you must make sure initialized the sdk in elsewhere,
  77. /// such as the native code in associated Android or iOS project.
  78. /// </para>
  79. ///
  80. /// <para>
  81. /// Default Level is <c>LogError</c>, so the LogError, LogException will auto report.
  82. /// </para>
  83. ///
  84. /// <para>
  85. /// You can call the method <code>BuglyAgent.ConfigAutoReportLogLevel(LogSeverity)</code>
  86. /// to change the level to auto report if you known what are you doing.
  87. /// </para>
  88. ///
  89. /// </summary>
  90. public static void EnableExceptionHandler ()
  91. {
  92. if (IsInitialized) {
  93. DebugLog (null, "BuglyAgent has already been initialized.");
  94. return;
  95. }
  96. 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.");
  97. // Register the LogCallbackHandler by Application.RegisterLogCallback(Application.LogCallback)
  98. _RegisterExceptionHandler ();
  99. }
  100. /// <summary>
  101. /// Registers the log callback handler.
  102. ///
  103. /// If you need register logcallback using Application.RegisterLogCallback(LogCallback),
  104. /// you can call this method to replace it.
  105. ///
  106. /// <para></para>
  107. /// </summary>
  108. /// <param name="handler">Handler.</param>
  109. public static void RegisterLogCallback (LogCallbackDelegate handler)
  110. {
  111. if (handler != null) {
  112. DebugLog (null, "Add log callback handler: {0}", handler);
  113. _LogCallbackEventHandler += handler;
  114. }
  115. }
  116. /// <summary>
  117. /// Sets the log callback extras handler.
  118. /// </summary>
  119. /// <param name="handler">Handler.</param>
  120. public static void SetLogCallbackExtrasHandler(Func<Dictionary<string, string>> handler){
  121. if (handler != null) {
  122. _LogCallbackExtrasHandler = handler;
  123. DebugLog(null, "Add log callback extra data handler : {0}", handler);
  124. }
  125. }
  126. /// <summary>
  127. /// Reports the exception.
  128. /// </summary>
  129. /// <param name="e">E.</param>
  130. /// <param name="message">Message.</param>
  131. public static void ReportException (System.Exception e, string message)
  132. {
  133. if (!IsInitialized) {
  134. return;
  135. }
  136. DebugLog (null, "Report exception: {0}\n------------\n{1}\n------------", message, e);
  137. _HandleException (e, message, false);
  138. }
  139. /// <summary>
  140. /// Reports the exception.
  141. /// </summary>
  142. /// <param name="name">Name.</param>
  143. /// <param name="message">Message.</param>
  144. /// <param name="stackTrace">Stack trace.</param>
  145. public static void ReportException (string name, string message, string stackTrace)
  146. {
  147. if (!IsInitialized) {
  148. return;
  149. }
  150. DebugLog (null, "Report exception: {0} {1} \n{2}", name, message, stackTrace);
  151. _HandleException (LogSeverity.LogException, name, message, stackTrace, false);
  152. }
  153. /// <summary>
  154. /// Unregisters the log callback.
  155. /// </summary>
  156. /// <param name="handler">Handler.</param>
  157. public static void UnregisterLogCallback (LogCallbackDelegate handler)
  158. {
  159. if (handler != null) {
  160. DebugLog (null, "Remove log callback handler");
  161. _LogCallbackEventHandler -= handler;
  162. }
  163. }
  164. /// <summary>
  165. /// Sets the user identifier.
  166. /// </summary>
  167. /// <param name="userId">User identifier.</param>
  168. public static void SetUserId (string userId)
  169. {
  170. if (!IsInitialized) {
  171. return;
  172. }
  173. DebugLog (null, "Set user id: {0}", userId);
  174. SetUserInfo (userId);
  175. }
  176. /// <summary>
  177. /// Sets the scene.
  178. /// </summary>
  179. /// <param name="sceneId">Scene identifier.</param>
  180. public static void SetScene (int sceneId)
  181. {
  182. if (!IsInitialized) {
  183. return;
  184. }
  185. DebugLog (null, "Set scene: {0}", sceneId);
  186. SetCurrentScene (sceneId);
  187. }
  188. /// <summary>
  189. /// Adds the scene data.
  190. /// </summary>
  191. /// <param name="key">Key.</param>
  192. /// <param name="value">Value.</param>
  193. public static void AddSceneData (string key, string value)
  194. {
  195. if (!IsInitialized) {
  196. return;
  197. }
  198. DebugLog (null, "Add scene data: [{0}, {1}]", key, value);
  199. AddKeyAndValueInScene (key, value);
  200. }
  201. /// <summary>
  202. /// Configs the debug mode.
  203. /// </summary>
  204. /// <param name="enable">If set to <c>true</c> debug mode.</param>
  205. public static void ConfigDebugMode (bool enable)
  206. {
  207. EnableDebugMode (enable);
  208. DebugLog (null, "{0} the log message print to console", enable ? "Enable" : "Disable");
  209. }
  210. /// <summary>
  211. /// Configs the auto quit application.
  212. /// </summary>
  213. /// <param name="autoQuit">If set to <c>true</c> auto quit.</param>
  214. public static void ConfigAutoQuitApplication (bool autoQuit)
  215. {
  216. _autoQuitApplicationAfterReport = autoQuit;
  217. }
  218. /// <summary>
  219. /// Configs the auto report log level. Default is LogSeverity.LogError.
  220. /// <example>
  221. /// LogSeverity { Log, LogDebug, LogInfo, LogWarning, LogAssert, LogError, LogException }
  222. /// </example>
  223. /// </summary>
  224. ///
  225. /// <param name="level">Level.</param>
  226. public static void ConfigAutoReportLogLevel (LogSeverity level)
  227. {
  228. _autoReportLogLevel = level;
  229. }
  230. /// <summary>
  231. /// Configs the default.
  232. /// </summary>
  233. /// <param name="channel">Channel.</param>
  234. /// <param name="version">Version.</param>
  235. /// <param name="user">User.</param>
  236. /// <param name="delay">Delay.</param>
  237. public static void ConfigDefault (string channel, string version, string user, long delay)
  238. {
  239. DebugLog (null, "Config default channel:{0}, version:{1}, user:{2}, delay:{3}", channel, version, user, delay);
  240. ConfigDefaultBeforeInit (channel, version, user, delay);
  241. }
  242. /// <summary>
  243. /// Logs the debug.
  244. /// </summary>
  245. /// <param name="tag">Tag.</param>
  246. /// <param name="format">Format.</param>
  247. /// <param name="args">Arguments.</param>
  248. public static void DebugLog (string tag, string format, params object[] args)
  249. {
  250. if(!_debugMode) {
  251. return;
  252. }
  253. if (string.IsNullOrEmpty (format)) {
  254. return;
  255. }
  256. Console.WriteLine ("[BuglyAgent] <Debug> - {0} : {1}", tag, string.Format (format, args));
  257. }
  258. /// <summary>
  259. /// Prints the log.
  260. /// </summary>
  261. /// <param name="level">Level.</param>
  262. /// <param name="format">Format.</param>
  263. /// <param name="args">Arguments.</param>
  264. public static void PrintLog (LogSeverity level, string format, params object[] args)
  265. {
  266. if (string.IsNullOrEmpty (format)) {
  267. return;
  268. }
  269. LogRecord (level, string.Format (format, args));
  270. }
  271. #if UNITY_EDITOR || UNITY_STANDALONE
  272. #region Interface(Empty) in Editor
  273. private static void InitBuglyAgent (string appId)
  274. {
  275. }
  276. private static void ConfigDefaultBeforeInit(string channel, string version, string user, long delay){
  277. }
  278. private static void EnableDebugMode(bool enable){
  279. }
  280. private static void SetUserInfo(string userInfo){
  281. }
  282. private static void ReportException (int type,string name, string message, string stackTrace, bool quitProgram)
  283. {
  284. }
  285. private static void SetCurrentScene(int sceneId) {
  286. }
  287. private static void AddKeyAndValueInScene(string key, string value){
  288. }
  289. private static void AddExtraDataWithException(string key, string value) {
  290. // only impl for iOS
  291. }
  292. private static void LogRecord(LogSeverity level, string message){
  293. }
  294. private static void SetUnityVersion(){
  295. }
  296. #endregion
  297. #elif UNITY_ANDROID
  298. // #if UNITY_ANDROID
  299. #region Interface for Android
  300. private static readonly string GAME_AGENT_CLASS = "com.tencent.bugly.agent.GameAgent";
  301. private static readonly int TYPE_U3D_CRASH = 4;
  302. private static readonly int GAME_TYPE_UNITY = 2;
  303. private static bool hasSetGameType = false;
  304. private static AndroidJavaClass _gameAgentClass = null;
  305. public static AndroidJavaClass GameAgent {
  306. get {
  307. if (_gameAgentClass == null) {
  308. _gameAgentClass = new AndroidJavaClass(GAME_AGENT_CLASS);
  309. // using (AndroidJavaClass clazz = new AndroidJavaClass(CLASS_UNITYAGENT)) {
  310. // _gameAgentClass = clazz.CallStatic<AndroidJavaObject> ("getInstance");
  311. // }
  312. }
  313. if (!hasSetGameType) {
  314. // set game type: unity(2).
  315. _gameAgentClass.CallStatic ("setGameType", GAME_TYPE_UNITY);
  316. hasSetGameType = true;
  317. }
  318. return _gameAgentClass;
  319. }
  320. }
  321. private static string _configChannel;
  322. private static string _configVersion;
  323. private static string _configUser;
  324. private static long _configDelayTime;
  325. private static void ConfigDefaultBeforeInit(string channel, string version, string user, long delay){
  326. _configChannel = channel;
  327. _configVersion = version;
  328. _configUser = user;
  329. _configDelayTime = delay;
  330. }
  331. private static bool _configCrashReporterPackage = false;
  332. private static void ConfigCrashReporterPackage(){
  333. if (!_configCrashReporterPackage) {
  334. try {
  335. GameAgent.CallStatic("setSdkPackageName", _crashReporterPackage);
  336. _configCrashReporterPackage = true;
  337. } catch {
  338. }
  339. }
  340. }
  341. private static void InitBuglyAgent(string appId)
  342. {
  343. if (IsInitialized) {
  344. return;
  345. }
  346. ConfigCrashReporterPackage();
  347. try {
  348. GameAgent.CallStatic("initCrashReport", appId, _configChannel, _configVersion, _configUser, _configDelayTime);
  349. _isInitialized = true;
  350. } catch {
  351. }
  352. }
  353. private static void EnableDebugMode(bool enable){
  354. _debugMode = enable;
  355. ConfigCrashReporterPackage();
  356. try {
  357. GameAgent.CallStatic("setLogEnable", enable);
  358. } catch {
  359. }
  360. }
  361. private static void SetUserInfo(string userInfo){
  362. ConfigCrashReporterPackage();
  363. try {
  364. GameAgent.CallStatic("setUserId", userInfo);
  365. } catch {
  366. }
  367. }
  368. private static void ReportException (int type, string name, string reason, string stackTrace, bool quitProgram)
  369. {
  370. ConfigCrashReporterPackage();
  371. try {
  372. GameAgent.CallStatic("postException", TYPE_U3D_CRASH, name, reason, stackTrace, quitProgram);
  373. } catch {
  374. }
  375. }
  376. private static void SetCurrentScene(int sceneId) {
  377. ConfigCrashReporterPackage();
  378. try {
  379. GameAgent.CallStatic("setUserSceneTag", sceneId);
  380. } catch {
  381. }
  382. }
  383. private static void SetUnityVersion(){
  384. ConfigCrashReporterPackage();
  385. try {
  386. GameAgent.CallStatic("setSdkConfig", "UnityVersion", Application.unityVersion);
  387. } catch {
  388. }
  389. }
  390. private static void AddKeyAndValueInScene(string key, string value){
  391. ConfigCrashReporterPackage();
  392. try {
  393. GameAgent.CallStatic("putUserData", key, value);
  394. } catch {
  395. }
  396. }
  397. private static void AddExtraDataWithException(string key, string value) {
  398. // no impl
  399. }
  400. private static void LogRecord(LogSeverity level, string message){
  401. if (level < LogSeverity.LogWarning) {
  402. DebugLog (level.ToString (), message);
  403. }
  404. ConfigCrashReporterPackage();
  405. try {
  406. GameAgent.CallStatic("printLog", string.Format ("<{0}> - {1}", level.ToString (), message));
  407. } catch {
  408. }
  409. }
  410. #endregion
  411. #elif UNITY_IPHONE || UNITY_IOS
  412. #region Interface for iOS
  413. private static bool _crashReporterTypeConfiged = false;
  414. private static void ConfigCrashReporterType(){
  415. if (!_crashReporterTypeConfiged) {
  416. try {
  417. _BuglyConfigCrashReporterType(_crashReporterType);
  418. _crashReporterTypeConfiged = true;
  419. } catch {
  420. }
  421. }
  422. }
  423. private static void ConfigDefaultBeforeInit(string channel, string version, string user, long delay){
  424. ConfigCrashReporterType();
  425. try {
  426. _BuglyDefaultConfig(channel, version, user, null);
  427. } catch {
  428. }
  429. }
  430. private static void EnableDebugMode(bool enable){
  431. _debugMode = enable;
  432. }
  433. private static void InitBuglyAgent (string appId)
  434. {
  435. ConfigCrashReporterType();
  436. if(!string.IsNullOrEmpty(appId)) {
  437. _BuglyInit(appId, _debugMode, _crashReproterCustomizedLogLevel); // Log level
  438. }
  439. }
  440. private static void SetUnityVersion(){
  441. ConfigCrashReporterType();
  442. _BuglySetExtraConfig("UnityVersion", Application.unityVersion);
  443. }
  444. private static void SetUserInfo(string userInfo){
  445. if(!string.IsNullOrEmpty(userInfo)) {
  446. ConfigCrashReporterType();
  447. _BuglySetUserId(userInfo);
  448. }
  449. }
  450. private static void ReportException (int type, string name, string reason, string stackTrace, bool quitProgram)
  451. {
  452. ConfigCrashReporterType();
  453. string extraInfo = "";
  454. Dictionary<string, string> extras = null;
  455. if (_LogCallbackExtrasHandler != null) {
  456. extras = _LogCallbackExtrasHandler();
  457. }
  458. if (extras == null || extras.Count == 0) {
  459. extras = new Dictionary<string, string> ();
  460. extras.Add ("UnityVersion", Application.unityVersion);
  461. }
  462. if (extras != null && extras.Count > 0) {
  463. if (!extras.ContainsKey("UnityVersion")) {
  464. extras.Add ("UnityVersion", Application.unityVersion);
  465. }
  466. StringBuilder builder = new StringBuilder();
  467. foreach(KeyValuePair<string,string> kvp in extras){
  468. builder.Append(string.Format("\"{0}\" : \"{1}\"", kvp.Key, kvp.Value)).Append(" , ");
  469. }
  470. extraInfo = string.Format("{{ {0} }}", builder.ToString().TrimEnd(" , ".ToCharArray()));
  471. }
  472. // 4 is C# exception
  473. _BuglyReportException(4, name, reason, stackTrace, extraInfo, quitProgram);
  474. }
  475. private static void SetCurrentScene(int sceneId) {
  476. ConfigCrashReporterType();
  477. _BuglySetTag(sceneId);
  478. }
  479. private static void AddKeyAndValueInScene(string key, string value){
  480. ConfigCrashReporterType();
  481. _BuglySetKeyValue(key, value);
  482. }
  483. private static void AddExtraDataWithException(string key, string value) {
  484. }
  485. private static void LogRecord(LogSeverity level, string message){
  486. if (level < LogSeverity.LogWarning) {
  487. DebugLog (level.ToString (), message);
  488. }
  489. ConfigCrashReporterType();
  490. _BuglyLogMessage(LogSeverityToInt(level), null, message);
  491. }
  492. private static int LogSeverityToInt(LogSeverity logLevel){
  493. int level = 5;
  494. switch(logLevel) {
  495. case LogSeverity.Log:
  496. level = 5;
  497. break;
  498. case LogSeverity.LogDebug:
  499. level = 4;
  500. break;
  501. case LogSeverity.LogInfo:
  502. level = 3;
  503. break;
  504. case LogSeverity.LogWarning:
  505. case LogSeverity.LogAssert:
  506. level = 2;
  507. break;
  508. case LogSeverity.LogError:
  509. case LogSeverity.LogException:
  510. level = 1;
  511. break;
  512. default:
  513. level = 0;
  514. break;
  515. }
  516. return level;
  517. }
  518. // --- dllimport start ---
  519. [DllImport("__Internal")]
  520. private static extern void _BuglyInit(string appId, bool debug, int level);
  521. [DllImport("__Internal")]
  522. private static extern void _BuglySetUserId(string userId);
  523. [DllImport("__Internal")]
  524. private static extern void _BuglySetTag(int tag);
  525. [DllImport("__Internal")]
  526. private static extern void _BuglySetKeyValue(string key, string value);
  527. [DllImport("__Internal")]
  528. private static extern void _BuglyReportException(int type, string name, string reason, string stackTrace, string extras, bool quit);
  529. [DllImport("__Internal")]
  530. private static extern void _BuglyDefaultConfig(string channel, string version, string user, string deviceId);
  531. [DllImport("__Internal")]
  532. private static extern void _BuglyLogMessage(int level, string tag, string log);
  533. [DllImport("__Internal")]
  534. private static extern void _BuglyConfigCrashReporterType(int type);
  535. [DllImport("__Internal")]
  536. private static extern void _BuglySetExtraConfig(string key, string value);
  537. // dllimport end
  538. #endregion
  539. #endif
  540. #region Privated Fields and Methods
  541. private static event LogCallbackDelegate _LogCallbackEventHandler;
  542. private static bool _isInitialized = false;
  543. private static LogSeverity _autoReportLogLevel = LogSeverity.LogError;
  544. private static int _crashReporterType = 1; // Default=0,1=Bugly-V2,MSDKBugly=2, IMSDKBugly=3
  545. #if UNITY_ANDROID
  546. // The crash reporter package name, default is 'com.tencent.bugly'
  547. private static string _crashReporterPackage = "com.tencent.bugly";
  548. #endif
  549. #if UNITY_IPHONE || UNITY_IOS
  550. private static int _crashReproterCustomizedLogLevel = 2; // Off=0,Error=1,Warn=2,Info=3,Debug=4
  551. #endif
  552. #pragma warning disable 414
  553. private static bool _debugMode = false;
  554. private static bool _autoQuitApplicationAfterReport = false;
  555. private static readonly int EXCEPTION_TYPE_UNCAUGHT = 1;
  556. private static readonly int EXCEPTION_TYPE_CAUGHT = 2;
  557. private static readonly string _pluginVersion = "1.5.1";
  558. private static Func<Dictionary<string, string>> _LogCallbackExtrasHandler;
  559. public static string PluginVersion {
  560. get { return _pluginVersion; }
  561. }
  562. public static bool IsInitialized {
  563. get { return _isInitialized; }
  564. }
  565. public static bool AutoQuitApplicationAfterReport {
  566. get { return _autoQuitApplicationAfterReport; }
  567. }
  568. private static void _SetCrashReporterType(int type){
  569. _crashReporterType = type;
  570. if (_crashReporterType == 2) {
  571. #if UNITY_ANDROID
  572. _crashReporterPackage = "com.tencent.bugly.msdk";
  573. #endif
  574. }
  575. }
  576. private static void _SetCrashReporterLogLevel(int logLevel){
  577. #if UNITY_IPHONE || UNITY_IOS
  578. _crashReproterCustomizedLogLevel = logLevel;
  579. #endif
  580. }
  581. private static void _RegisterExceptionHandler ()
  582. {
  583. try {
  584. // hold only one instance
  585. #if UNITY_5
  586. Application.logMessageReceived += _OnLogCallbackHandler;
  587. #else
  588. Application.RegisterLogCallback (_OnLogCallbackHandler);
  589. #endif
  590. AppDomain.CurrentDomain.UnhandledException += _OnUncaughtExceptionHandler;
  591. _isInitialized = true;
  592. DebugLog (null, "Register the log callback in Unity {0}", Application.unityVersion);
  593. } catch {
  594. }
  595. SetUnityVersion ();
  596. }
  597. private static void _UnregisterExceptionHandler ()
  598. {
  599. try {
  600. #if UNITY_5
  601. Application.logMessageReceived -= _OnLogCallbackHandler;
  602. #else
  603. Application.RegisterLogCallback (null);
  604. #endif
  605. System.AppDomain.CurrentDomain.UnhandledException -= _OnUncaughtExceptionHandler;
  606. DebugLog (null, "Unregister the log callback in unity {0}", Application.unityVersion);
  607. } catch {
  608. }
  609. }
  610. private static void _OnLogCallbackHandler (string condition, string stackTrace, LogType type)
  611. {
  612. if (_LogCallbackEventHandler != null) {
  613. _LogCallbackEventHandler (condition, stackTrace, type);
  614. }
  615. if (!IsInitialized) {
  616. return;
  617. }
  618. if (!string.IsNullOrEmpty (condition) && condition.Contains ("[BuglyAgent] <Log>")) {
  619. return;
  620. }
  621. if (_uncaughtAutoReportOnce) {
  622. return;
  623. }
  624. // convert the log level
  625. LogSeverity logLevel = LogSeverity.Log;
  626. switch (type) {
  627. case LogType.Exception:
  628. logLevel = LogSeverity.LogException;
  629. break;
  630. case LogType.Error:
  631. logLevel = LogSeverity.LogError;
  632. break;
  633. case LogType.Assert:
  634. logLevel = LogSeverity.LogAssert;
  635. break;
  636. case LogType.Warning:
  637. logLevel = LogSeverity.LogWarning;
  638. break;
  639. case LogType.Log:
  640. logLevel = LogSeverity.LogDebug;
  641. break;
  642. default:
  643. break;
  644. }
  645. if (LogSeverity.Log == logLevel) {
  646. return;
  647. }
  648. _HandleException (logLevel, null, condition, stackTrace, true);
  649. }
  650. private static void _OnUncaughtExceptionHandler (object sender, System.UnhandledExceptionEventArgs args)
  651. {
  652. if (args == null || args.ExceptionObject == null) {
  653. return;
  654. }
  655. try {
  656. if (args.ExceptionObject.GetType () != typeof(System.Exception)) {
  657. return;
  658. }
  659. } catch {
  660. if (UnityEngine.Debug.isDebugBuild == true) {
  661. UnityEngine.Debug.Log ("BuglyAgent: Failed to report uncaught exception");
  662. }
  663. return;
  664. }
  665. if (!IsInitialized) {
  666. return;
  667. }
  668. if (_uncaughtAutoReportOnce) {
  669. return;
  670. }
  671. _HandleException ((System.Exception)args.ExceptionObject, null, true);
  672. }
  673. private static void _HandleException (System.Exception e, string message, bool uncaught)
  674. {
  675. if (e == null) {
  676. return;
  677. }
  678. if (!IsInitialized) {
  679. return;
  680. }
  681. string name = e.GetType ().Name;
  682. string reason = e.Message;
  683. if (!string.IsNullOrEmpty (message)) {
  684. reason = string.Format ("{0}{1}***{2}", reason, Environment.NewLine, message);
  685. }
  686. StringBuilder stackTraceBuilder = new StringBuilder ("");
  687. StackTrace stackTrace = new StackTrace (e, true);
  688. int count = stackTrace.FrameCount;
  689. for (int i = 0; i < count; i++) {
  690. StackFrame frame = stackTrace.GetFrame (i);
  691. stackTraceBuilder.AppendFormat ("{0}.{1}", frame.GetMethod ().DeclaringType.Name, frame.GetMethod ().Name);
  692. ParameterInfo[] parameters = frame.GetMethod ().GetParameters ();
  693. if (parameters == null || parameters.Length == 0) {
  694. stackTraceBuilder.Append (" () ");
  695. } else {
  696. stackTraceBuilder.Append (" (");
  697. int pcount = parameters.Length;
  698. ParameterInfo param = null;
  699. for (int p = 0; p < pcount; p++) {
  700. param = parameters [p];
  701. stackTraceBuilder.AppendFormat ("{0} {1}", param.ParameterType.Name, param.Name);
  702. if (p != pcount - 1) {
  703. stackTraceBuilder.Append (", ");
  704. }
  705. }
  706. param = null;
  707. stackTraceBuilder.Append (") ");
  708. }
  709. string fileName = frame.GetFileName ();
  710. if (!string.IsNullOrEmpty (fileName) && !fileName.ToLower ().Equals ("unknown")) {
  711. fileName = fileName.Replace ("\\", "/");
  712. int loc = fileName.ToLower ().IndexOf ("/assets/");
  713. if (loc < 0) {
  714. loc = fileName.ToLower ().IndexOf ("assets/");
  715. }
  716. if (loc > 0) {
  717. fileName = fileName.Substring (loc);
  718. }
  719. stackTraceBuilder.AppendFormat ("(at {0}:{1})", fileName, frame.GetFileLineNumber ());
  720. }
  721. stackTraceBuilder.AppendLine ();
  722. }
  723. // report
  724. _reportException (uncaught, name, reason, stackTraceBuilder.ToString ());
  725. }
  726. private static void _reportException (bool uncaught, string name, string reason, string stackTrace)
  727. {
  728. if (string.IsNullOrEmpty (name)) {
  729. return;
  730. }
  731. if (string.IsNullOrEmpty (stackTrace)) {
  732. stackTrace = StackTraceUtility.ExtractStackTrace ();
  733. }
  734. if (string.IsNullOrEmpty (stackTrace)) {
  735. stackTrace = "Empty";
  736. } else {
  737. try {
  738. string[] frames = stackTrace.Split ('\n');
  739. if (frames != null && frames.Length > 0) {
  740. StringBuilder trimFrameBuilder = new StringBuilder ();
  741. string frame = null;
  742. int count = frames.Length;
  743. for (int i = 0; i < count; i++) {
  744. frame = frames [i];
  745. if (string.IsNullOrEmpty (frame) || string.IsNullOrEmpty (frame.Trim ())) {
  746. continue;
  747. }
  748. frame = frame.Trim ();
  749. // System.Collections.Generic
  750. if (frame.StartsWith ("System.Collections.Generic.") || frame.StartsWith ("ShimEnumerator")) {
  751. continue;
  752. }
  753. if (frame.StartsWith ("Bugly")) {
  754. continue;
  755. }
  756. if (frame.Contains ("..ctor")) {
  757. continue;
  758. }
  759. int start = frame.ToLower ().IndexOf ("(at");
  760. int end = frame.ToLower ().IndexOf ("/assets/");
  761. if (start > 0 && end > 0) {
  762. trimFrameBuilder.AppendFormat ("{0}(at {1}", frame.Substring (0, start).Replace (":", "."), frame.Substring (end));
  763. } else {
  764. trimFrameBuilder.Append (frame.Replace (":", "."));
  765. }
  766. trimFrameBuilder.AppendLine ();
  767. }
  768. stackTrace = trimFrameBuilder.ToString ();
  769. }
  770. } catch {
  771. PrintLog(LogSeverity.LogWarning,"{0}", "Error to parse the stack trace");
  772. }
  773. }
  774. PrintLog (LogSeverity.LogError, "ReportException: {0} {1}\n*********\n{2}\n*********", name, reason, stackTrace);
  775. _uncaughtAutoReportOnce = uncaught && _autoQuitApplicationAfterReport;
  776. ReportException (uncaught ? EXCEPTION_TYPE_UNCAUGHT : EXCEPTION_TYPE_CAUGHT, name, reason, stackTrace, uncaught && _autoQuitApplicationAfterReport);
  777. }
  778. private static void _HandleException (LogSeverity logLevel, string name, string message, string stackTrace, bool uncaught)
  779. {
  780. if (!IsInitialized) {
  781. DebugLog (null, "It has not been initialized.");
  782. return;
  783. }
  784. if (logLevel == LogSeverity.Log) {
  785. return;
  786. }
  787. if ((uncaught && logLevel < _autoReportLogLevel)) {
  788. //DebugLog (null, "Not report exception for level {0}", logLevel.ToString ());
  789. return;
  790. }
  791. string type = null;
  792. string reason = null;
  793. if (!string.IsNullOrEmpty (message)) {
  794. try {
  795. if ((LogSeverity.LogException == logLevel) && message.Contains ("Exception")) {
  796. Match match = new Regex (@"^(?<errorType>\S+):\s*(?<errorMessage>.*)", RegexOptions.Singleline).Match (message);
  797. if (match.Success) {
  798. type = match.Groups ["errorType"].Value.Trim();
  799. reason = match.Groups ["errorMessage"].Value.Trim ();
  800. }
  801. } else if ((LogSeverity.LogError == logLevel) && message.StartsWith ("Unhandled Exception:")) {
  802. Match match = new Regex (@"^Unhandled\s+Exception:\s*(?<exceptionName>\S+):\s*(?<exceptionDetail>.*)", RegexOptions.Singleline).Match(message);
  803. if (match.Success) {
  804. string exceptionName = match.Groups ["exceptionName"].Value.Trim();
  805. string exceptionDetail = match.Groups ["exceptionDetail"].Value.Trim ();
  806. //
  807. int dotLocation = exceptionName.LastIndexOf(".");
  808. if (dotLocation > 0 && dotLocation != exceptionName.Length) {
  809. type = exceptionName.Substring(dotLocation + 1);
  810. } else {
  811. type = exceptionName;
  812. }
  813. int stackLocation = exceptionDetail.IndexOf(" at ");
  814. if (stackLocation > 0) {
  815. //
  816. reason = exceptionDetail.Substring(0, stackLocation);
  817. // substring after " at "
  818. string callStacks = exceptionDetail.Substring(stackLocation + 3).Replace(" at ", "\n").Replace("in <filename unknown>:0","").Replace("[0x00000]","");
  819. //
  820. stackTrace = string.Format("{0}\n{1}", stackTrace, callStacks.Trim());
  821. } else {
  822. reason = exceptionDetail;
  823. }
  824. //// for LuaScriptException
  825. //if(type.Equals("LuaScriptException") && exceptionDetail.Contains(".lua") && exceptionDetail.Contains("stack traceback:")) {
  826. // stackLocation = exceptionDetail.IndexOf("stack traceback:");
  827. // if(stackLocation > 0) {
  828. // reason = exceptionDetail.Substring(0, stackLocation);
  829. // // substring after "stack traceback:"
  830. // string callStacks = exceptionDetail.Substring(stackLocation + 16).Replace(" [", " \n[");
  831. // //
  832. // stackTrace = string.Format("{0}\n{1}", stackTrace, callStacks.Trim());
  833. // }
  834. //}
  835. }
  836. }
  837. } catch {
  838. }
  839. if (string.IsNullOrEmpty (reason)) {
  840. reason = message;
  841. }
  842. }
  843. if (string.IsNullOrEmpty (name)) {
  844. if (string.IsNullOrEmpty (type)) {
  845. type = string.Format ("Unity{0}", logLevel.ToString ());
  846. }
  847. } else {
  848. type = name;
  849. }
  850. //����Lua�쳣�ϱ�
  851. if (type.Equals("LuaException")) return;
  852. _reportException (uncaught, type, reason, stackTrace);
  853. }
  854. private static bool _uncaughtAutoReportOnce = false;
  855. #endregion
  856. }