(插播)unity的 异常捕捉和 ios Android 崩溃信息的捕捉。

最近 做些准备性得工作和有意思的事情。所以最近做了一个适合ios和android 错误信息捕捉的unity插件。

两个功能,app崩溃也就是闪退 是开发者 很头疼的一件事,还有就是一些莫名得错误 有时候也会困扰着我们。现在,unity已经封装得挺好了,及时出现数组越界,和空对象这样严重得错误也不会崩溃,听着挺好,但是这给开发者带了很多烦恼啊。因为有时候可能出错了 你要跟就不知道 ,在什么地方出得错误啊。所以我们要想办法去解决这个问题。

我们都知道及时app崩溃,其实后台还是在运行得 只不过是 到了另一个线程去处理崩溃得一些问题。那好我们就可以去捕捉到错误,供我们去理解这个问题。

首先 我们先针对 ios闪退得错误得问题。我们知道 现在ios还是才去得OC编程,身为一个编译性得语言,一般很小得一个错误都会造成整个app得崩溃。

接下来 我们说下原理。 对于 IOS的机制是,它专门有一个类来处理异常错误。那就是NSException类,来处理各种错误得一个类。我们要的就是这个类中得一个通知,就是 在app出现异常崩溃的事后会通知得一个方法C语言的NSSetUncaughtExceptionHandler。我们就是用这个方法来进行 异常注册。

 NSSetUncaughtExceptionHandler(&caughtExceptionHandler);

其中  caughtExceptionHandler是自己写得类中得一个C语言得方法。

void caughtExceptionHandler(NSException *e){}

可以看到 在这个方法中我们就可以拿到NSException得错误得指针。就可以得到所有得错误得信息。

这里知道了一半,信息我们是得到了,但是app现在是处于崩溃中,我们想让我们的错误信息传到服务器或者返回给开发者得处理平台。那我们得线程必须等待才可以,这样才能给我们时间把错误信息上传到处理平台。那怎么才能把线程阻塞调那 正好 ios有线程进入等待得方法CFRunLoopRunInMode()

好了想好这个多 我们开始 进行实施了。

这是 异常获取得方法,把此方法 进行注册 也就是

-(void) _registerException{
     NSSetUncaughtExceptionHandler(&caughtExceptionHandler);
}
void caughtExceptionHandler(NSException *e){
    NSString *currentTime = [[VKCatchCrash shareCatchCrash] getCurrentTime];
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

    NSArray *arr = [e callStackSymbols];
    NSString *reason = [e reason];
    NSString *name = [e name];

    NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
    [dic setValue:[[VKCatchCrash shareCatchCrash] _getDeviceInfo] forKey:@"device"];
    [dic setValue:arr forKey:@"callStackSymbols"];
    [dic setValue:reason forKey:@"reason"];
    [dic setValue:name forKey:@"name"];
    [dic setObject:currentTime forKey:@"time"];

    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];
    if ([jsonData length] > 0 && error == nil){
        NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        NSString *path = [[VKCatchCrash shareCatchCrash] fullScreenshots:currentTime];

        //if([[VKCatchCrash shareCatchCrash] checkNetwork]){
            [Upload startUpload:[Upload initUpBackBlock:^(NSData *data, NSURLResponse *response, NSError *error) {
                NSFileManager *manager =   [NSFileManager defaultManager];
                if([manager fileExistsAtPath:path]){
                [manager removeItemAtPath:path error:nil];
                }
            } upUrl:HOST upDelegate:nil formName:@"fileField" filePath:path contentKey:[[NSArray alloc] initWithObjects:@"bug", nil] contentValue:[[NSArray alloc] initWithObjects:jsonString, nil]]];
//        }
        NSLog(@"%@",jsonString);
        [[VKCatchCrash shareCatchCrash] performSelectorOnMainThread:@selector(alertUploadBug) withObject:nil waitUntilDone:YES];

         while (!dismiss)
        {
            for (NSString *mode in (__bridge NSArray *)allModes)
            {
              CFRunLoopRunInMode((__bridge CFStringRef)mode, 0, false);
            }
        }
        CFRelease(allModes);
        NSSetUncaughtExceptionHandler(NULL);
    }else{
        NSLog(@"nil");
    }
}

警告框提示app闪退。

-(void)alertUploadBug{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"产生莫名得崩溃,报告正在发送服务器!" message:nil delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alert show];
}

当前时间

-(NSString *)getCurrentTime{
    NSDate * senddate=[NSDate date];
    NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init];
    [dateformatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
    NSString * locationString=[dateformatter stringFromDate:senddate];
    return locationString;
}

这里还用到了一个 自己写的额一个上传得类VKHttpManager,回来我会上传 源码。

基本信息就这么多。详情可以看下 源码。

下面我们 我们来说下Android得闪退得异常捕获。

Android相对于ios比较简单,只要使用一个类来接口UncaughtExceptionHandler就可以了

然后有借口得方法,会自动调用该回调。

public class MyCrashHandler  implements UncaughtExceptionHandler{
	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
}
}

其中 Throwable得异常对象就是我们需要得异常对象。

其中这里也有 和ios相似得地方 那就是 线程阻塞

Looper.prepare();

Looper.loop();

这里有一个地方要注意得就是 在安卓中 unity调用 AndroidUI得东西 要使用 UI线程不然是无法显示。详情见下面得源码

UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {  

}
};

然后 unity里我们还要做些东西来捕获unity得异常和对ios和Android进行对接得一些东西。

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class CatchCrash : MonoBehaviour {

	private static string HOST ="http://192.168.1.240/game/";
	private static string currentTime = "";

#if UNITY_IPHONE
	[DllImport ("__Internal")]
	private static extern void registerException (string host);
	[DllImport ("__Internal")]
	private static extern void createBug ();
	[DllImport ("__Internal")]
	private static extern void unityBugAlert (string msg);
	[DllImport ("__Internal")]
	private static extern string getDeviceInfo ();

#elif UNITY_ANDROID
	AndroidJavaClass jc = null;
	AndroidJavaObject jo = null;
#endif
	// Use this for initialization
	void Awake () {

#if UNITY_EDITOR

#elif UNITY_IPHONE || UNITY_ANDROID
		DontDestroyOnLoad (gameObject);
		Application.RegisterLogCallback(OnLog);
#endif

#if UNITY_IPHONE
		registerException (HOST);
#elif UNITY_ANDROID
		jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
		jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
		jo.Call("registerException",HOST);
#endif
	}

	void OnLog (string message, string stacktrace, LogType type)
	{
		if (type == LogType.Exception)
		{
			currentTime = getcurrentTime().ToString();
			string butMsg = "{\n"+
				"\"message\":" +"\""+message.Replace("\n","")+"\""+
					",\n\"stacktrace\":"+"\""+stacktrace.Replace("\n","")+"\""+
					",\n\"time\":"+"\""+currentTime+"\""
							+"\n" +
					"\"device\":" +"\""+
#if UNITY_IPHONE
					getDeviceInfo().Replace("\n","")+"\""+
#elif UNITY_ANDROID
					jo.CallStatic<string>("getDeviceInfo").Replace("\n","")+"\""+
#endif
								"\n}";
			StartCoroutine(uploadBug(butMsg));
#if UNITY_IPHONE
			unityBugAlert (butMsg);
#elif UNITY_ANDROID
			jo.CallStatic("unityBugAlert",butMsg);
#endif
		}
	} 

	IEnumerator uploadBug(string butMsg){
		yield return new WaitForEndOfFrame();
		int width = Screen.width;
		int height = Screen.height;
		Texture2D tex = new Texture2D (width,height,TextureFormat.RGB24, false);
		tex.ReadPixels(new Rect(0, 0, width, height), 0, 0 );
		tex.Apply();
		byte [] bytes = tex.EncodeToPNG ();

		WWWForm form = new WWWForm();
		form.AddField ("bug",butMsg);
		form.AddBinaryData ("fileField",bytes,currentTime+".png","image/png");

		WWW w = new WWW (HOST,form);
		yield return w;
		if (w.error != null) {
			Debug.Log (" upload bug erro");
		} else {
			Debug.Log (" upload bug finish");
		}
	}

	public static string getcurrentTime()
	{
		System.DateTime now = System.DateTime.Now;
		return now.Year + "-" + now.Month + "-" + now.Day + " " + now.Hour + ":" + now.Minute + ":" + now.Second;
	}
}

工程再次哦

(插播)unity的 异常捕捉和 ios Android 崩溃信息的捕捉。

时间: 2024-10-07 05:34:49

(插播)unity的 异常捕捉和 ios Android 崩溃信息的捕捉。的相关文章

Cocos2d-x Lua 播放视频(iOS&amp;android)

最近刚转了游戏,来公司不久就接到一个任务就是做一个视频播放的功能,自己花了3天时间,暂时实现了一个简易的功能,特写篇博客,以作记录. 参考地址如下: http://blog.csdn.net/xiaominghimi/article/details/6870259 http://blog.csdn.net/kaitiren/article/details/11832851 http://blog.csdn.net/candyforever/article/details/8905852 实现功能

常用获取Android崩溃日志和IOS崩溃日志的几种方法

一:前言 在日常测试app时,经常会遇到崩溃问题,测试快速抓取到崩溃日志可以有效方便开发进行定位,快速解决问题所在测试做到测试分析,定位是非常重要的,这也是判断一个测试能力指标的一大维度. 二:Android崩溃日志 一.通过adb logcat获取 # 清除日志,新手上路时,日志内容很多,对于能毕现的日志,可以先清除后重新获取 adb logcat -c # 然后再次运行崩溃操作,再抓取日志 # 存储日志到当前目录下的 carsh.log 中 adb logcat -d *:W > crash

用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)

本文为原创,如有转载,请注明出处:http://www.cnblogs.com/jackybu 前言 章节: 1.需求描述以及c/c++实现日期和月历的基本操作 2.ios实现自绘日期选择控件 3.android实现自绘日期选择控件 目的: 通过一个相对复杂的自定义自绘控件来分享: 1.ios以及android自定义自绘控件的开发流程 2.objc与c/c++混合编程 3.android ndk的环境配置,android studio ndk的编译模式,swig在android ndk开发中的作

移动端热更新方案(iOS+Android)

PPT资源包含iOS+Android 各种方案分析:https://github.com/qiyer/Share/blob/master/%E7%83%AD%E6%9B%B4%E6%96%B0%E5%88%86%E4%BA%ABPPT.pptx 一 .热更新(热修复)产品背景 这里谈到的热更新都是指APP(不包含网页).APP按大类别可以粗略分为 应用 和 游戏.APP的开发周期是极其快速的,在实际开发流程中,我们总会有一些需求迫使我们短时间内快速上线,比如需求流程出错,程序员主观导致的一些bu

ios/android 程序员

1.负责IOS/Android平台客户端的开发和维护. 2.两年以上IOS/Android/Java/Object-C开发经验,能够独立进行IOS或Android 客户端开发: 3.熟练掌握APP SDK中UI.网络.数据库.XML/JSON解析等开发技巧,熟悉APP开发环境: 4.对终端产品的UI/UE有独到的见解与认识,追求良好的用户体验: 5.对手机软件性能优化.内存优化有一定经验 6.对软件产品有强烈的责任心,具备良好的沟通能力和优秀的团队协作能力. asp.net 程序员 1.负责项目

[掌眼]iOS / Android / java / node.js 通用的 AES256 加解密算法

example.m NSString *text = @"text"; NSString *key32 = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding]; NSString *encryptedData = [[data AES256EncryptWithKey:key32] base64EncodedStringWi

iOS/Android 浏览器(h5)及微信中唤起本地APP

在移动互联网,链接是比较重要的传播媒质,但很多时候我们又希望用户能够回到APP中,这就要求APP可以通过浏览器或在微信中被方便地唤起. 这是一个既直观又很好的用户体验,但在实现过程中会遇到各种问题: 如何解决未安装APP时的做好引导页 如何在微信中唤醒APP 在iOS9中如何处理universal link被用户误关的情况 如何解决Android各种机型.各种第三方浏览器导致的兼容问题等 在APP未安装情况下,引导用户下载后打开APP后,如何进入之前唤起时指定的页面或内容,即如何实现场景还原 在

C/C++/IOS/Android/MFC/python等软件定制服务,有人需要吗?

服务内容: 欢迎光临本店http://isoftware.taobao.com/,本地承接各种软件定制服务.主要包括如下四大类: 1.C,C++,MFC,visual studio开发 2.iOS/Android 手机App开发 3.matlab/python/R语言程序开发 4.计算机专业.自动化控制专业,机器学习.模式识别等软件程序 团队介绍: 宏佳科技团队成员都是来自浙大的硕士和博士,曾任职于华为.百度等知名大公司,长期从事软件开发工作,具有丰富的软件开发经验.团队从2011年组建起就开始

iOS开发拓展篇—UIDynamic(捕捉行为)

iOS开发拓展篇—UIDynamic(捕捉行为) 一.简介 可以让物体迅速冲到某个位置(捕捉位置),捕捉到位置之后会带有一定的震动 UISnapBehavior的初始化 - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; UISnapBehavior常见属性 @property (nonatomic, assign) CGFloat damping; 用于减幅.减震(取值范围是0.0