Jon
Jon

Reputation: 1850

Finding Exception Cause from Vague Stack Trace

I have an Android app that has recently been mysteriously force closing for some of my users using 4.x devices. Looking at the exception stack, it seems like the error occurs before any of my code ever gets run, but I assume I am doing something that is causing this.

*Is something wrong with how I am finding my cause or stack? Otherwise, if this is a full stack trace is it really possible that Android fails before any of my code is ever run? *

I find the latter unlikely since I register my UncaughtExceptionHandler in my Application's onCreate() method, and I usually a get a file from my user.

My error logging code is below:

I implement an extended Thread.UncaughtExceptionHandler using the app's . When an error occurs I write the exception info out to a log in uncaughtException(Thread thread,Throwable ex). This is how I find the Strings to print:

    // Get exception info

    String newLine = "\r\n";
    String message = "Message: " + ex.getMessage();
    String cause = "Cause: " + ex.getCause();
    StackTraceElement[] stes = ex.getStackTrace();
    String stack;

    // build stack trace

    stack = "Stack: " + newLine;

    for ( int i = 0; i < stes.length; i++ )
        {
        stack += stes[i].toString();
        stack += newLine;
        }

    // print out message
    // print out cause
    // print out stack

Which outputs this to a file:

Message: Unable to create application com.(Modified app name for anonimity).*.*Application: java.lang.IllegalArgumentException Cause: java.lang.IllegalArgumentException Stack: android.app.ActivityThread.handleBindApplication(ActivityThread.java:4254) android.app.ActivityThread.access$1400(ActivityThread.java:140) android.app.ActivityThread$H.handleMessage(ActivityThread.java:1297) android.os.Handler.dispatchMessage(Handler.java:99) android.os.Looper.loop(Looper.java:137) android.app.ActivityThread.main(ActivityThread.java:4921) java.lang.reflect.Method.invokeNative(Native Method) java.lang.reflect.Method.invoke(Method.java:511) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805) dalvik.system.NativeStart.main(Native Method)

P.S. Yes, I know about ACRA, but I do not want to use it at this time.

Upvotes: 0

Views: 1214

Answers (2)

Jon
Jon

Reputation: 1850

@micha still is the accepted answer, but I figured I would show my modified solution based on his answer.

      @Override
public void uncaughtException(Thread thread, Throwable ex)
    {
    // This needs to be AIR TIGHT!. Do everything in a try-catch to prevent
    // any exceptions from EVER occurring here. If an error does occur here 
    // then we will hang
    // indefinitely and get an ANR.
    try
        {
        FileManager fileMgr = FileManager.getInstance( myApp );
        String logName = "ErrorLog.log";

        // print exception to byte array

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PrintStream printer = new PrintStream( out );
        ex.printStackTrace( printer );

        // write out byte array as string to log file.

        fileMgr.writeToLogFile( logName, out.toString(), false );
        }
    catch ( Exception e )
        {
        }

    // This allows the system to handle to exception and close the App.

    defaultHandler.uncaughtException( thread, ex );
    }

My custom FileManager class does the actual writing to the file, but I used Throwable's printStackTrace() to get the full stack trace, which was much deeper then I could have done on my own.

Upvotes: 1

micha
micha

Reputation: 49572

Maybe your application is causing an exception which is caught and then rethrown.

You are only printing the Stacktrace of the last Exception. Maybe this exception has a cause (ex.getCause() is not null). In this case you should also print the stacktrace of the cause (An maybe the cause of the cause..).

You don't have to do this on your own. Throwable has a nice method for this which prints the complete stacktrace and backtrace to a PrintStream:

public void printStackTrace(PrintStream s)

After that you only have to write the printStream into your log.

Upvotes: 1

Related Questions