Do some preparatory work and interesting things recently. So I recently made a unity plugin for iOS and Android error messages capture.
Two features, app crashes is a headache for developers, and there are some inexplicable mistakes that can sometimes haunt us. Now that unity is well encapsulated, the array is out of bounds in time, and the empty object is so badly wrong that it doesn't crash, it sounds good, but it gives developers a lot of trouble. Because sometimes it may be wrong, you have to follow and do not know, where the wrong ah. So we have to find a way to solve this problem.
We all know in time the app crashes, but in fact the background is still running just to another thread to deal with some of the crashes. Well, then we can go and catch the error, for us to understand the problem.
First of all, we're going to be wrong about the iOS flash back. We know that now iOS still go to OC programming, as a compiled language, generally very small error will cause the entire app to crash.
Next we say the principle. The mechanism for iOS is that it specifically has a class to handle exception errors. That is the NSException class, to handle all kinds of errors to get a class. What we want is a notification in this class that the Nssetuncaughtexceptionhandler of a method C is notified after the app crashes unexpectedly. We are using this method to register the exception.
Nssetuncaughtexceptionhandler (&caughtexceptionhandler);
One of the Caughtexceptionhandler is the method of writing a C language in a class.
void Caughtexceptionhandler (NSException *e) {}
We can see that in this method we can get the nsexception of the wrong pointer. You can get all the wrong information.
Here we know half of the information we got, but the app is now in a crash, and we want to get our error message to the server or back to the developer's processing platform. Then we have to wait for the thread to be able to give us time to upload the error message to the processing platform. So how do I get the thread to jam that just right iOS wired into the Wait Method Cfrunloopruninmode ()
Well, think about this a lot and we're starting to implement it.
This is the method of exception acquisition, and registering this method is
-(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 optio Ns: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) {to (NSString *mode in (__bridge NSarray *) allmodes) {Cfrunloopruninmode ((__bridge cfstringref) mode, 0, false); }} cfrelease (Allmodes); Nssetuncaughtexceptionhandler (NULL); }else{NSLog (@ "nil"); }}
A warning box prompts the app to flash back.
-(void) alertuploadbug{ uialertview *alert = [[Uialertview alloc] initwithtitle:@ "generates an inexplicable crash, the report is sending the server! "Message:nil delegate:self cancelbuttontitle:@" OK "otherbuttontitles:nil, nil]; [Alert show];}
Current time
-(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;}
Here also used a self-written amount of an uploaded class Vkhttpmanager, back I will upload the source code.
The basic information is so much. Details can be seen under the source code.
Below us we're going to have an abnormal capture of the Android Flash back.
Android is relatively simple compared to iOS, as long as you use a class to interface Uncaughtexceptionhandler.
Then there is an excuse for the method that will automatically invoke the callback.
public class Mycrashhandler implements uncaughtexceptionhandler{@Overridepublic void Uncaughtexception (Thread Thread, Throwable ex) {}}
Where the Throwable exception object is what we need to be the exception object.
Where there's a similar place to iOS that's thread blocking
Looper.prepare ();
Looper.loop ();
Here's a place to be aware that wirelessly unity calls Androidui to use the UI thread or it can't be displayed. See the source below for details.
UnityPlayer.currentActivity.runOnUiThread (New Runnable () { @Override public void Run () { }};
And then in unity we're going to do something to catch unity's anomaly and get something to do with iOS and Android.
Using unityengine;using system.collections;using system.runtime.interopservices;public class CatchCrash: Monobehaviour {private static string HOST = "http://192.168.1.240/game/";p rivate 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_androidandroidjavaclass JC = null; Androidjavaobject Jo = null; #endif//Use this for initializationvoid awake () {#if Unity_editor#elif Unity_iphone | | Unity_androiddontdestroyonload (Gameobject); Application.registerlogcallback (OnLog); #endif # if Unity_iphoneregisterexception (HOST); #elif UNITY_ANDROIDJC = 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_ Iphonegetdeviceinfo (). Replace ("\ n", "") + "\" "+ #elif unity_androidjo.callstatic<string> (" Getdeviceinfo "). Replace ("\ n", "") + "\" "+ #endif" \ n} "; Startcoroutine (Uploadbug (butmsg)), #if Unity_iphoneunitybugalert (butmsg); #elif unity_androidjo.callstatic (" Unitybugalert ", butmsg); #endif}} IEnumerator Uploadbug (string butmsg) {yield return new waitforendofframe (); int width = S Creen.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);M.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 ("Uploa D 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 again Oh