博客
关于我
(插播)unity的 异常捕捉和 ios Android 崩溃信息的捕捉。
阅读量:792 次
发布时间:2023-01-24

本文共 3634 字,大约阅读时间需要 12 分钟。

一个适合 iOS 和 Android 错误信息捕捉的 Unity 插件

随着应用程序的复杂性不断提升,开发者在日常工作中遇到崩溃和莫名错误的问题越来越频繁。这些问题不仅会导致用户体验下降,还可能导致应用在发布后面临用户投诉和bad sectors的风险。在此背景下,我开发了一个能够捕捉iOS和Android端的错误信息的Unity插件,旨在帮助开发人员更好地定位和解决问题。

背景介绍

在开发过程中,尤其是针对移动应用,应用程序的崩溃和异常处理是一个非常棘手的问题。与桌面应用程序相比,移动应用程序的资源更为受限,而开发者还需要确保在错误发生时能够快速处理,以避免用户流失。

对于iOS,尤其是 ZhObject-C 的编程特性,使得任何一个小错误都可能导致整个程序崩溃。类似地,Android端虽然更为包容,但在处理资源的管理上也可能出现意想不到的错误。因此,一个能够全方位捕捉操作系统、框架和应用程序本身错误的插件显得尤为必要。

该插件的主要功能

该插件基于以下原理,旨在为开发者提供一个全面的错误处理和信息收集框架:

  • 错误信息的捕捉:无论是应用程序突然的 crash,还是方向欺骗导致的不确定错误,这个插件都能够对相关信息进行捕捉和保存。
  • 设备信息的收集:包括设备型号、系统版本、运行环境等关键信息,帮助定位问题所在。
  • 错误堆栈和调用信息:对于iOS,捕捉 Objective-C 的错误堆栈信息;对于 Android,则捕捉其相关的 Throwable 对象。
  • 实现原理

    iOS 错误处理

    iOS 的异常处理机制基于其Objective-C语言特性,旨在为开发者提供一个广泛的错误信息处理框架。主要步骤包括:

    • 注册异常处理器:使用 NSSetUncaughtExceptionHandler 注册一个自定义的异常处理器,确保在未被捕获的异常发生时能够得到称为
    • 处理异常信息:在自定义异常处理器中,获取异常对象,并从中提取调用信息、堆栈信息和错误原因
    • 线程堵塞处理:确保在捕捉完错误信息后,进行适当的线程堵塞处理,以便能够及时上传错误信息

    Android 错误处理

    相较于iOS,Android 的错误处理机制更加简单,主要步骤如下:

    • 注册未捕获异常处理器:在 AndroidManifest.xml 中定义一个自定义的未捕获异常处理器类,确保在未被捕获的异常发生时调用相应的方法
    • 获取异常信息:获取 Throwable 对象,并从中提取相关错误信息
    • UI 线程处理:确保所有 UI 操作都在 UI 线程上执行,以避免因线程问题导致的新错误

    插件适配方法

    为了确保插件能够适配不同开发环境,以下方法被采用:

    • iOS 适配
      • 使用 C 的交叉调用技术通过 native 方法来实现错误信息的捕捉和处理
      • 在需要展示错误信息时,使用 UIAlertView 弹出提示框,供用户查看错误详情
    • Android 适配
      • 使用 Java Reflection 和 JNI 绑定 yawt 到 Unity 的错误信息捕捉机制
      • 确保所有 UI 操作都在 UI 线程上执行,以避免因线程问题导致的新错误

    具体实现细节

    错误信息的捕捉与处理

    对于iOS,捕捉的是 Objective-C 的错误堆栈信息,对于 Android则捕捉的是 Throwable 对象中的相关信息。具体实现如下:

    • iOS
      - (void)caughtExceptionHandler:(NSException *exception) {
      NSString *currentTime = [self getCurrentTime];
      CFRunLoopRef runLoop = CFRunLoopGetCurrent();
      CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
      NSArray *callStack = [exception callStackSymbols];
      NSString *reason = [exception reason];
      NSString *name = [exception name];
      NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
      [dictionary setValue:callStack forKey:@"callStack"];
      [dictionary setValue:reason forKey:@"reason"];
      [dictionary setValue:name forKey:@"name"];
      [dictionary setValue:currentTime forKey:@"time"];
      NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:nil];
      if (jsonData.length > 0) {
      NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
      // 如果网络条件满足:
      [[VKCatchCrash shareCatchCrash] performSelectorOnMainThread:@selector(uploadBug) withObject:nil waitUntilDone:YES];
      while (!dismiss) {
      for (NSString *mode in (__bridge NSArray *)allModes) {
      CFRunLoopRunInMode((__bridge CFStringRef)mode, 0, false);
      }
      }
      CFRelease(allModes);
      NSSetUncaughtExceptionHandler(NULL);
      }
      }
    • Android
      public class MyCrashHandler implements UncaughtExceptionHandler {
      @Override
      public void uncaughtException(Thread thread, Throwable ex) {
      Throwable throwable = ex;
      StringBuilder message = new StringBuilder();
      message.append("应用程序在 ");
      message.append(DateTimeFormatter.ofPattern("MM-dd HH:mm:ss").format(new Date(throwable_TC.getTime())));
      message.append(" 发生了 crash! 原因: ");
      message.append(throwable.getCause().getMessage() != null ? throwable.getCause().getMessage() : "未捕获错误信息");
      uploadCrashInfo(message.toString(), throwable.getStackTrace().join("\n"));
      }
      }

    开发工具

    为了实现上述功能,我使用了以下工具和库:

    • iOS
      • Objective-C 语言
      • Core Foundation 和 CFRunLoop
      • NSException 处理逻辑
    • Android
      • Java语言
      • Android SDK 和 NDK
      • Reflection 和 JNI 绑定

    总结

    通过上述方法,我成功开发了一个能够适配iOS和Android的错误信息捕捉插件。该插件不仅能够快速定位应用程序的 crash 信息,还可以提取相关的调用堆栈和错误原因,便于开发和优化。在实际应用中,我还扩展了一些功能,如错误信息的本地存储和远程上传,确保开发人员能够快速获得所需的开发反馈。

    转载地址:http://rgeyk.baihongyu.com/

    你可能感兴趣的文章
    EdgeX Foundry:边缘计算的创新平台
    查看>>
    EdgeX Foundry:边缘计算的未来趋势与应用
    查看>>
    Edge浏览器打开控制台后程序总是停止进入debug模式关闭教程【八仙过海之又一过海方案】
    查看>>
    Educational Codeforces Round 28
    查看>>
    Educational Codeforces Round 47 (Rated for Div. 2)F. Dominant Indices 线段树合并
    查看>>
    ed编辑器--适用于shell脚本内编辑文件的最最简单编辑器
    查看>>
    "SQLServer复制需要有实际的服务器名称才能连接到服务器,请指定实际的服务器名"转...
    查看>>
    EF 资料
    查看>>
    EF6.0中出现未找到具有固定名称“System.Data.SqlClient”的 ADO.NET提供程序的实体框架提供程序解决办法...
    查看>>
    EF6与MVC5系列(4):在MVC应用程序中使用弹性连接和命令拦截
    查看>>
    Effective C# 学习笔记(四十五)减少装箱拆箱行为
    查看>>
    Effective Modern C++:02auto
    查看>>
    efficientnet最合适的尺寸和最后一层的层数
    查看>>
    EF三种编程方式详细图文教程(C#+EF)之Database First
    查看>>
    Ehcache Java开源缓存框架
    查看>>
    EhCache 分布式缓存/缓存集群
    查看>>
    EHR:对人力资源信息系统的认识
    查看>>
    EJB学习笔记六(EJB中的拦截器)
    查看>>
    el-form表单重置后输入失效
    查看>>
    el-select下拉框修改背景色
    查看>>