zoukankan      html  css  js  c++  java
  • (插播)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如今是处于崩溃中,我们想让我们的错误信息传到server或者返回给开发人员得处理平台。那我们得线程必须等待才干够。这样才干给我们时间把错误信息上传到处理平台。

    那怎么才干把线程堵塞调那 正好 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:@"产生莫名得崩溃,报告正在发送server。" 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 = "{
    "+
    				""message":" +"""+message.Replace("
    ","")+"""+
    					",
    "stacktrace":"+"""+stacktrace.Replace("
    ","")+"""+
    					",
    "time":"+"""+currentTime+"""
    							+"
    " +
    					""device":" +"""+
    #if UNITY_IPHONE
    					getDeviceInfo().Replace("
    ","")+"""+
    #elif UNITY_ANDROID
    					jo.CallStatic<string>("getDeviceInfo").Replace("
    ","")+"""+
    #endif
    								"
    }";
    			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;
    	}
    }
    

    project再次哦













  • 相关阅读:
    CodeForces 650C Table Compression
    HDU 5632 Rikka with Array [想法题]
    HDU 4352 XHXJ's LIS
    HDU 5634 Rikka with Phi
    HDU 4763 Theme Section
    LightOJ 1342 Aladdin and the Magical Sticks [想法题]
    HDU 4578 Transformation
    POJ 1177 Picture
    HDU 4614 Vases and Flowers
    SPOJ AEROLITE
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5067062.html
Copyright © 2011-2022 走看看