Making my application crash more gracefully - android

I have an app that is running pretty stably (no more crashes actually), but as everybody knows your program crashes as soon as it gets in the hands of somebody else :D
What I would like is to find a(all) the place(s) where I can put a try{}catch(){} to be able catch and control what happens when the app crashes unexpectedly (display a better message, send log, possible recovery...)
I know its surely not that simple but still it would be good if there was a way to catch most of them.
(for example there is a small bug in GLSurfaceView that when it is being closed causes sometimes to crash because of an EGL swap buffer)
any ideas?

You should take a look at this article: http://stuffthathappens.com/blog/2007/10/07/programmers-notebook-uncaught-exception-handlers/
But be careful when using this, you might mask errors in your application and if you resort to this to just pretend your app is working, you're doing it wrong :)

Here's a really lazy way to catch any given exception:
try {
//do some stuff here
} catch (Throwable e) {
//handle exception here
}
This is useful if you have no idea what's going to be thrown. Consequently, it's not going to be very helpful for any kind of recovery. This is something I wouldn't use beyond the testing period of development.

Related

Thousands of java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds exceptions in crashlytics

First of all thanks in advance....i hope you can help me, i am a bit lost in this.
I am asking here besides there is a lost of threads talking about this, because i do not find a solution here neither in internet.... it seems to happen 99% on Samsung devices, since 4.2 version. And i really hope i am not the first one asking this and you can give me an answer, whatever is good or bad :). But i do not know if it is a Samsung issue or general, i also have seen it in other devices but only a few crashes...in samsung is thousands... ¿?¿?
We have in our apps crashlitycs integrated, and from some time ago, we started to receive different crashes, but we do not even know if they are crashes for real or not. The exception is being throw is:
Fatal Exception: java.util.concurrent.TimeoutException
com.android.internal.os.BinderInternal$GcWatcher.finalize() timed out after 10 seconds
It happens in different objects: BinderInternal, Binder, NativeDecimalFormat, BinderProxy, CloseGuard, WindowsCursor etc.
This did not happen before...and when i am trying to look in internet i just get a lot people is affected but there is no solution.
My biggest fear is....when is happening? is crashing people when using the app or just in background? is it crashing with the Android OS message "the app stopped suddenly"? or is something internal i can "ignore" ?
Is it happening all days a lot times every day, is it constant....but we cannot reproduce it anyway.......do you know what is this?
I give you some links they talk about garbage collector issue, or bad finalize/internet call issue....
How to handle :java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds errors?
https://www.reddit.com/r/androiddev/comments/3am3yb/some_crash_reports_have_nothing_to_do_with_my_app/
https://github.com/andstatus/andstatus/issues/301
http://openstackwiki.org/wiki/Java.util.concurrent.TimeoutException_(android.media.MediaMetadataRetriever.finalize)_Zeit%C3%BCberschreitung_nach_10_Sekunden
We solved the problem by stopping the FinalizerWatchdogDaemon.
public static void fix() {
try {
Class clazz = Class.forName("java.lang.Daemons$FinalizerWatchdogDaemon");
Method method = clazz.getSuperclass().getDeclaredMethod("stop");
method.setAccessible(true);
Field field = clazz.getDeclaredField("INSTANCE");
field.setAccessible(true);
method.invoke(field.get(null));
}
catch (Throwable e) {
e.printStackTrace();
}
}
You can call the method in Application's lifecycle, like attachBaseContext().
For the same reason, you also can specific the phone's manufacture to fix the problem, it's up to you.

Catch "Unfortunately 'app' has stopped working" Error

I am using a very unstable library on Android that crashes sporadically. I start it using the startActivity() in my code.
The unstable part of the code is doing a lot of video processing and uploading the result to a server. I do not really mind if the activity crashes, but I need to signal the server that it did.
The crash comes from a memory leak (no time to solve it yet). Is there a way I can catch the error a display a more friendly/funny message instead?
try {
context.startActivity(intent);
} catch (ApplicationCrashedException e) {
server.notifyServerOfCrash();
toast("I really disliked your face...");
}
Edit: Here is the Error:
java.lang.OutOfMemoryError
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at java.nio.MemoryBlock.allocate(MemoryBlock.java:125)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:72)
at io.cine.android.streaming.FFmpegMuxer.writeSampleData(FFmpegMuxer.java:151)
at io.cine.android.streaming.AndroidEncoder.drainEncoder(AndroidEncoder.java:128)
at io.cine.android.streaming.TextureMovieEncoder.handleFrameAvailable(TextureMovieEncoder.java:264)
at io.cine.android.streaming.TextureMovieEncoder$EncoderHandler.handleMessage(TextureMovieEncoder.java:409)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at io.cine.android.streaming.TextureMovieEncoder.run(TextureMovieEncoder.java:219)
at java.lang.Thread.run(Thread.java:841)
For some reason once the BroadcastActivity runs out of memory, the Activity gets killed and comes back to the previous one. It then displays the 'app' has stopped working Dialog. If I press OK, it kills the entire application and comes back to the home screen.
Ideally I would just have it come back to the previous activity notifying the server silently. (Not killing the application)
Is there a way I can catch the error a display a more friendly/funny message instead?
If the app is leaking so much memory that it crashes, you cannot easily catch this.
Why you can't always catch this
When you start running out of memory, exceptions are thrown from any part of your app's code that tries to allocate more memory than is available. So it isn't just your library that will throw the exceptions.
How you could detect this
Catch the OutOfMemoryError and make an effort to tell user/server
Your results will vary, but you could wrap the Thread's run() method with a try catch pair and try to catch the out of memory error. You will still be out of memory and any thing you do in the catch code might fail because of it. Still it might work if the process frequently allocates large chunks of memory which would mean there is still a little bit left.
Example:
public void run() {
try {
//video process code
} catch (OutOfMemoryError error) {
//we are still out of memory so these operations might fail
tellServerWeFailed();
triggeruserDialog();
}
}
onTrimMemory() override
You could also try stopping your video tasks when onTrimMemory() is called. Your mileage may vary, I've never been able to get it to work consistently across different Android devices.
Error Reporting Framework
One solution that is pretty involved is to use a third party error reporting framework as they will often let you show your user custom crash messages.
Check out http://www.acra.ch/ and specifically the documentation on User Messages
Started Service
I do not really mind if the activity crashes, but I need to signal the server that it did.
Great! What you might try is to use a started service that android automatically relaunches after the crash. The details on how to tell your server are up to you. You might find that you will need to save some token or other information so that you can tell your server which session has ended so you might, for example, always keep that information saved in Preference entry and read it out after the crash.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(LOG_TAG, "Received start id " + startId + ": " + intent);
if (intent == null) {
Log.w(LOG_TAG, "Service was stopped and automatically restarted by the system. ");
//Tell your server about the crash.
stopSelf();
}
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
See http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle
More about running out of memory on Android
To maintain a functional multi-tasking environment, Android sets a hard limit on the heap size for each app. The exact heap size limit varies between devices based on how much RAM the device has available overall. If your app has reached the heap capacity and tries to allocate more memory, it will receive an OutOfMemoryError.
In some cases, you might want to query the system to determine exactly how much heap space you have available on the current device—for example, to determine how much data is safe to keep in a cache. You can query the system for this figure by calling getMemoryClass(). This returns an integer indicating the number of megabytes available for your app's heap. This is discussed further below, under Check how much memory you should use. (source)
Some key points:
Your entire app shares the system-assigned memory heap.
Once you've leaked memory, it is gone until the application is restarted.
You won't be able to segregate memory leaked in one activity by leaving that activity.
If you are looking for the type of Exception to catch, just repeat the steps you took to make your app crash and take a look at the logcat. You should see a message like "SomeTypeOfException thrown" catch that.
Edit: otherwise use the generic Exception

prevent app termination when general exception happens

Is there a way to catch, in one place, all "uncaught" exceptions and let the app continue?
I see I can use setUncaughtExceptionHandler to do some logging and whatever, but the app will still terminate. I want something where I can log an exception, tell the user his action failed, and let him keep going (try something else).
Thanks.
No. I'm not sure why you'd want it. Catch Exceptions from methods that are known to throw them, and test your code to avoid Exceptions such as NullPointerException. That's the way to write good code.
Sorry to revisit such an old thread but since there's no proper answer to it I felt obliged to provide a solution.
Add this to the activity that opens every time the app is used (MainActivity for example) -
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("Exception"+Thread.currentThread().getStackTrace()[2],paramThrowable.getLocalizedMessage());
}
});
What it does is that it sets a default handler for uncaught exceptions and doesn't quit the app when one pops up. However, with great power comes great responsibility. I don't recommend you use this as a way to escape the responsibility of catching exceptions in your code (by using a try-catch for example). Test your code to make it as bug-free as possible before launch.

Can't Catch NetworkOnMainThreadException

I know what causes a NetworkOnMainThreadException, as well as how to fix it, but for the purposes of improving the development experience, I'd like to be able to catch the exception and at least log the event or alert the user (who is still the developer at this point)...
Strangely, I'm not having any luck with this code (which sends and receives over my TCP socket):
try
{
toServer.println (msg.trim());
resp = fromServer.readLine();
}
catch (android.os.NetworkOnMainThreadException nex)
{ ... do something here ... }
Eclipse doesn't recognize that exception at all, and I copy-pasta-ed the exception type from the Android Developer website -- I'm pretty sure I spelled it right...
Is there something I don't know about Java (perhaps) that makes this exception uncatchable??
Thanks,
R.
Is there something I don't know about Java (perhaps) that makes this exception uncatchable??
Yes, StrictMode makes it uncatchable. Either way though, you should not catch this exception. Instead, you should implement your code correctly by wrapping your code in an AsyncTask. The reason why this exception is thrown is to prevent you from slowing down your application by blocking the UI thread.
Read my blog post for more info:
Why Ice Cream Sandwich Crashes Your App
Well I just tested this on my version of eclipse, and it works just fine.. I guess I would check which version of the api you are using? looks like to throw that exception you need a minimum api version 11. Otherwise perhaps eclipse is to blame? All I know is that this code is correct and should be executing without any issues.
Are you sure this is the first use of networking in your application?
If you are connecting to a server usually at that time NetworkOnMainThreadException should be thrown. Try adding a log statement before the try and see if it shows up. If it does not the Exception is thrown earlier.

Android Market Error Handling

I have some required try/catch statements in my application that in my testing never get called. I have sent them up with:
Log.e("messaage", e.toString());
for my debugging and now that I'm ready to release I am not sure if I should take that out or not. I see in android market you can get error/crash reports and while I do not expect my app to catch any errors, I would like to know if that happens and wondering if I need specific syntax for that. My question is what should I do in the catch statement for these errors? I'm already handling the error from a user standpoint...
Thanks!
IMHO logging is not really necessary, but sooner or later you will catch something. Acra may be of interest to you, if you want to be notified of these occasions.

Categories

Resources