Handling errors in GLThread.run() - android

I just released a new version of my application to the Android market, and my new version has a GLSurfaceView in the activity. Even though I'm not doing anything fancy, I have a large user base, there's a lot of substandard Android phones out there, and I'm invariably getting exceptions in GLThread.run().
What is the recommended way to catch/handle these exceptions without crashing the entire app? Ideally I'd like to be able to catch the error, remove the surface view from the activity and switch off the component that uses OpenGL. I did a bit of searching but mostly found exception reports for Firefox on Android and stuff like that. :)
I'm thinking of just using an uncaught exception handler, switching a shared preferences flag to false, and letting it crash; the next run I won't try to add that GLSurfaceView.

I ended up working around the problem with the following code:
final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
if (thread.getName().startsWith("GLThread")) {
disableOpenGLStuff();
}
// You could wrap this in an else, but I'm not sure how good of an idea it is to leave the application running when a thread has crashed.
defaultHandler.uncaughtException(thread, ex);
});

Related

Is there an 'emergency plan' in the Android API?

Is there a way to execute a method after the App crashed (a certain number times)?
Example: Sometimes with every run data changes in a way that the app does not crash anymore. So, this way it may recover itself after trying to start it for 2 times for example. The 3rd time would run smoothly again. Just an example!
My only idea right now would be to wrap everything inside the onCreate method in my main Activity in a generic try-catch block (catching Exception) handler. I don't think this is smart for several reasons, for example performance.
To catch every uncaught exception you can use following snippet:
public class App extends Application {
public void onCreate() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
Log.e("TAG","Implement your recovery strategy here, e.g. clean database or cache: " + e.toString());
}
});
}
}
Please note, that this is very 'hacky' solution, and if your app is in corrupted state very often there is probably something wrong with your code.

How to have a callback for when a crash occurred, while using Crashlytics SDK?

Background
We use Crashlytics SDK to manage app crashes and get needed information about them.
So far, the information that the SDK automatically gathered was enough
The problem
I'd like to add more information for each crash, such as: available&total heap memory, activity stack,...
Thing is, I don't see a way to achieve this.
I know that the way Android framework works with unhandled exceptions is pretty easy (using Thread.setDefaultUncaughtExceptionHandler) and it's probably how the SDK works, but I can't find where to use the listener of the SDK itself.
What I've tried
The SDK has a listener, but it seems it's not of the current session, as shown here. The function name is "crashlyticsDidDetectCrashDuringPreviousExecution" , meaning it's of the previous session. Same callback was available before in deprecated methods.
There are "Custom Logging" and "Custom Keys" features, but those occur when I call them (not right when the crash occurs).
The question
Is there a way to add extra information to Crashlytics right when a crash occurs ?
If so, how?
Try creating an UncaughtExceptionHandler and use Custom Key(s) to store the information you want to be associated with your crash report.
Create your custom UncaughtExceptionHandler (ensuring that it will pass exception to default UncaughtExceptionHandler to be handled later via Crashlytics).
In the uncaughtException method add custom logic to set your key e.g. Crashlytics.setString("available_memory", "5784");
Check your Crashlytics dashboard to view your custom key(s) when your app crashes
Create a custom Application subclass to hold your logic:
public class MyApplication extends Application {
private static Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler;
private static Thread.UncaughtExceptionHandler mCaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
// Custom logic goes here
// Calculate available memory
Crashlytics.setString("available_memory", "5784");
// This will make Crashlytics do its job
mDefaultUncaughtExceptionHandler.uncaughtException(thread, ex);
}
};
#Override
public void onCreate() {
super.onCreate();
// Order is important!
// First, start Crashlytics
Crashlytics.start(this);
// Second, cache a reference to default uncaught exception handler
mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
// Third, set custom UncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(mCaughtExceptionHandler);
}
}
Remember to specify the name of your Application subclass in your AndroidManifest.xml’s tag
<application android:name="MyApplication">

Random app crashes while starting application in android

Sometimes my application crashes while trying to open it. As the app hasn't completely started I don't get an error report. I also can't connect my application to the emulator because this behaviour is not reproducable. Sometimes it just crashes once. In other times I can try to open/reopen it as often as I want and it works perfect.
I only use the network-connection (no camera and other stuff). I don't have any services which could crash the application and I tried to reproduce my error by trying to stop the application while it loads something in the background - no success at all.
What do you think could be the reason for crashing? How can I get a log-file, stacktrace something useful for fixing this problem? I simply can't reproduce it so I never see a Logcat-Output when it occurs.
It might be a Fragment-Initializing-Problem but I can't see my mistake. This never occured before and it's just not a common mistake. It might crash only once/twice a week - but it crashes in some point in time...
I've uploaded my project on github but I don't think this is helping somehow.
My main question is: What for opportunities do I have to see what might be the reason behind these random crashes?
Root your phone and install CatLog. When it crashes, open CatLog and save the log so you can view it later.
Or try this if you want to automate it:
Create an exception handler that saves a stack trace to a file.
public class UncaughtExceptionSaver implements UncaughtExceptionHandler{
UncaughtExceptionHandler previousHandler;
Context context;
public UncaughtExceptionSaver (Context context){
this.context = context;
previousHandler= Thread.getUncaughtExceptionHandler();
}
#Override
void uncaughtException(Thread t, Throwable e){
/*Save the stacktrace from the throwable to a
file in your external directory, using context. */
previousHandler.uncaughtException(t,e);
}
}
Then in an Application subclass, call this in the onCreate method:
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionSaver(this));

Android: CalledFromWrongThreadException from WebView's shouldOverrideUrlLoading

I am developing on a library that is somehow getting a CalledFromWrongThread Exception crash on Samsung Galaxy S1 (api v7 - android 2.1). The code is something like this:
class MyWebViewClient extends WebViewClient {
#Override
public void shouldOverrideUrlLoading(WebView view, String url) {
someListener.addToUiView();
}
}
and of course, the method that is actually throwing the error (which implements a listener callback):
View v;
public void addToUiView(){
v.addView(new TextView(context)); //<-- this line is throwing the error on rare occasions
}
I'm skipping some code in between, but i'm not doing anything weird in other places. Also note: this crash only seems to have been happening a very very small % of the time. (not necessarily conclusive, as not everyone reports their data).
has anyone else come across this?? Is WebCore threading messing things up?
Now I haven't actually tested this but I am going to answer to the best of my knowledge. That said, my instinct is telling me that you are only seeing the error intermittently because web requests from a WebView (browser) happen with varying levels of asynchronicity and probably utilize a thread pool to accomplish this. Basically, sometimes it requests resources in parallel and sometimes it doesn't. Worse yet you might be seeing this error on only a single device because OEMs optimize OS level code (like the WebView internals) based on their preferences and opinions (especially Samsung). Either way the real problem is that you are doing something "UI related" in a place that is definitely not guaranteed to be "UI friendly"... That is, anywhere where you are getting a subsystem callback.
The solution to your problem is much more simpler than the explanation: just use your context (that I am assuming is an Activity)..
Activitys have a built in function called runOnUiThread(Runnable) that will guard the code inside the runnable from running on the wrong thread. Basically, your problem is really common and android has a built-in solution. runOnUiThread will only add overhead if required, in other words if your thread is the UI thread, it will just run the Runnable, if it isn't it uses the correct Handler (the one associated with the UI thread) to run the Runnable.
Here is what it should look like:
View v;
public void addToUiView() {
final Activity activity = (Activity) context;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
v.addView(new TextView(activity));
}
});
}
i coded that up right inside the SO window so my apologies for any egregious errors, I hope that helps, and let me know if you need more info or of this doesn't solve your problem -ck

Does setting Thread.setDefaultUncaughtExceptionHandler prevent Google's error-reporting from work?

In my Android application I utilize setDefaultUncaughtExceptionHandler to store information about unhandled exceptions locally on a user device. After some feedback I suspect that this code prevents the built-in Google's error-reporting feature from work, because I do not see error reports in the developer console, while exceptions are reported by users. Their devices are well past 2.2, where the error-reporting was introduced. Could it be that specific device with, say, 4.0.3 does not support this feature? If yes, how can I detect this programmatically?
I can't find information regarding this in Android documentation. I'd like both standard error-reporting and my custom handling work together. In my custom exception handler I call Thread.getDefaultUncaughtExceptionHandler() to get default handler, and in my implementation of uncaughtException I propagate exception to this default handler as well.
I first tried calling System.exit(1); as mentioned in this SO answer, but that didn't work.
Finally solved it by calling the uncaughtException(Thread thread, Throwable ex) again on Androids default UncaughtExceptionHandler (found it by checking the ACRA source code.
Example Activity
public class MainActivity extends Activity implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler _androidUncaughtExceptionHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_androidUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
// Rest onCreate
setContentView(R.layout.main_activity);
}
//#Override
public void uncaughtException(Thread thread, Throwable ex) {
try {
// Do your stuff with the exception
} catch (Exception e) {
/* Ignore */
} finally {
// Let Android show the default error dialog
_androidUncaughtExceptionHandler.uncaughtException(thread, ex);
}
}
}
Yes, this will stop the inbuilt error report. The user is given a dialog when your app crashes, with an option to report the error via Google Play. However, if you use setDefaultUncaughtExceptionHandler() then the exception is handled within your app, and no option is given to report it.
I recommend that you integrate ACRA into your project, as it allows you to easily receive error reports upon crashes.

Categories

Resources