Reputation: 1850
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
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
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