I need to handle crashes in android application,Is there any callback function or overridden method in activity class which will be called when the app crashes?
Guide me in solving this...
You can set an uncaught exception handler which will be called every time. Like this
final Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
// do your magic
defaultHandler.uncaughtException(thread, throwable);
}
});
You should probably subclass the Application class and run this code as the first thing in the OnCreate method. Getting the default handler and passing the exception along is to ensure proper handling after you are done performing magic.
What are you trying to achieve?
Related
I want to send a firebase crash report for every uncaught exception in my app but I also want to Android system to show the "App has stopped responding" dialog. How do I go about this?? I already have an UncaughtException handler that sends the firebase crash report. My issue now is letting Android handle the rest of the process.
The uncaught exception can be delegated back to system by storing the old exception handler and passing uncaught exceptions to it.
First create an Application class as below:
public class Controller extends Application {
private static Thread.UncaughtExceptionHandler defaultHandler;
#Override
public void onCreate() {
super.onCreate();
if (defaultHandler == null) {
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
}
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
FirebaseCrash.report(e); //or whatever
defaultHandler.uncaughtException(t, e); //this will show crash dialog.
}
});
}
}
Then use this class as application in the manifest as:
<application
android:name=".Controller"
... />
I am trying to make use of HandlerThread in android and am ending up with either a situation in which the UI thread is not responding anymore, or a strange IllegalStateException. I want to give you a minimal example of my problem.
I have a class DataManager which instantiates a worker thread on creation:
public class DataManager
{
private final HandlerThread loaderThread = new HandlerThread( "Worker" );
private final Producer loader;
Inside of this class I have my Handler defined:
private static class Producer extends Handler
{
public Producer( Looper looper )
{
super( looper );
}
#Override
public void handleMessage( Message msg )
{
msg.recycle();
}
}
The constructor of my DataManager runs the worker thread and associates the handler with the thread's looper:
public DataManager()
{
loaderThread.start();
this.loader = new Producer( loaderThread.getLooper() );
}
Before DataManager is destroyed, it stops the thread and waits for it to finish. Actually I believe this part is not relevant to my problem, because my DataManager instance is definitely alive all the time:
#Override
protected void finalize() throws Throwable
{
loaderThread.quit();
loaderThread.join();
super.finalize();
}
Finally, I have doSomething method, which simply posts a message to the worker thread:
public void doSomething()
{
Message msg = Message.obtain();
loader.sendMessage( msg );
}
Now I'm instantiating the DataManager from inside of a custom view on the UI thread. When the view is about to paint itself using onDraw it calls doSomething on the DataManager. The further behavior depends on whether an AsyncTask is currently running in background or not:
If it is running, than the UI thread is becoming unresponsive form this moment on.
Otherwise, I get an IllegalStateException, thrown from within a subroutine of Looper.loop of the UI thread, saying:
IllegalStateException: The specified message queue synchronization barrier token has not been posted or has already been removed.
Google gives absolutely no results for this message. I've been reading documentation and searching for similar problems for a few hours now and still have no idea what I might be doing wrong. Any ideas?
Got it. Obsiously the situation about recycling messages is this:
If you send it to a handler, the handler/looper will recycle it for you.
So one must not recycle the message within handleMessage.
My app is a hybrid html5 + JS + android which run in webview and communicate so much with Andorid through JS interface.
I got some report that it fails after 2 second on some devices. I added ACRA so I can get reports, but I didn't get any thing.
So I tried to test it myself, To raise an exception I add a code that manipulate views of main thread in Javascript interface's function which was triggered with a button in html. This raise an exception: Only the original thread that created a view hierarchy can touch its views. Now the app start and when I tap the button it exit with exception and ACRA send the report.
Then I put the manipulation code in a function of JS interface which was called immediately after the app start. now app is closed after a second. But ACRA doesn't send any error. Even an ExceptionHandler didn't catch it but catch the first case.
This is the log of second scenario:
59): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy#43f8d990 (uid=10019 pid=329)
12-15 01:18:07.047: WARN/dalvikvm(409): JNI WARNING: JNI method called with exception raised
12-15 01:18:07.047: WARN/dalvikvm(409): in Landroid/webkit/BrowserFrame;.stringByEvaluatingJavaScriptFromString (Ljava/lang/String;)Ljava/lang/String; (NewString)
12-15 01:18:07.057: WARN/dalvikvm(409): Pending exception is:
12-15 01:18:07.057: INFO/dalvikvm(409): Landroid/view/ViewRoot$CalledFromWrongThreadException;: Only the original thread that created a view hierarchy can touch its views
I don't know what this pending exception is? I couldn't find anything on web. I wonder why dont ACRA or Exception Handler catch it?
class JavaScriptInterface
{
MyActivity parent;
JavaScriptInterface(MyActivity parent)
{
this.parent = parent;
}
public void immediatelyCalled()
// Webview load index.html in oncreate of activity and js inside html calls this function immediately
{
parent.textview1.setText("test");
// raise an exception which ACRA or Exception Handler dont catch
// Problem is here
}
public void buttonCalled()
// This is called when a button is tapped in html
{
parent.textview1.setText("test");
// raise an exception which Exception Handler and ACRA catch
}
}
this is my activity:
public class MyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
class MyExceptionHandler implements Thread.UncaughtExceptionHandler
{
#Override
public void uncaughtException(Thread thread, Throwable throwable)
{
Log.d("ExceptionHandler", "Caught exception: " + throwable.getClass().getName() + ": " + throwable.getMessage());
}
}
MyExceptionHandler handler = new MyExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(handler);
this.wv = (WebView) findViewById(R.id.webview);
this.wv.addJavascriptInterface(new JavaScriptInterface(this), "android");
this.ws = this.wv.getSettings();
this.ws.setJavaScriptEnabled(true);
this.wv.loadUrl("file:///android_asset/index.html");
}
}
this is part of index.html:
<script type="text/javascript">
android.immediatelyCalled();
</scritp>
<button onclick="android.buttonCalled()"></button>
Tested on AVD 2.2 and Xperai Arc 4.0.3, Both the same
I think the method immediatelyCalled() is called in another thread than the one you are creating "MyActivity parent" (a UI thread, your apps main thread). So an uncaught exception handler which you assign to the ui thread and which has nothing to do with the process which is running the javascript code, can not catch this exception occuring at setText (accessing a view which belongs to another thread).
I think you could catch the exception of course if you enclose parent.textview1.setText("test"); in a try catch block.
You should be able to avoid the exception if you modify the setText call in this way:
parent.textView1.post(new Runnable() {
public void run() {
parent.textview1.setText("test");
}
});
You'll have to mark your parent parameter as final.
Unfortunately i have no eclipse here to test and it's late already :)
good luck!
I added an exceptionhandler for unhandled exceptions, to know that the app has crashed on the next app start:
#Override
public void uncaughtException(Thread thread, Throwable ex) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putString("crashed", "yes");
editor.commit();
}
I added the handler via:
Thread.setDefaultUncaughtExceptionHandler(this);
Now the thing is: since I added the handler, the app behaves differently on error:
Before I added the handler I got a popup telling me that the app has crashed.
Now, after adding the handler the app just freezes, and after a while android shows me a popup telling me that the app does not respond anymore and whether I want to wait any longer. This is not good IMO. Any hints, how to properly exit after an application crash?
you can save the original exception handler , so that you can call it after you are done with doing your own custom operations on the unhandled exception . something like this:
//Inside UncaughtExceptionHandler.java:
…
private UncaughtExceptionHandler defaultUEH;
public DefaultExceptionHandler()
{
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
#Override
public void uncaughtException(Thread t, Throwable e)
{
//do anything you wish about the Throwable e :getStackTrace(),getCause(),getClass()...
//call the original uncaught exception handler:
defaultUEH.uncaughtException(t, e);
}
I suggest that you integrate your logic with ACRA, so that it can handle the issues of crash reporting and cleanup.
I'm trying to create a simple multiplayer game. There's a WorkerService which is supposed to handle all network communication and all interaction between this service and my Activities is done with AIDL. I think this is a standard approach - to enable two way interaction I use also an IWorkerCallback interface (also AIDL).
The problem is that callbacks have to change things in UI which may be done only in UI thread. I've created a Handler (in UI thread) and believed that this is an obvious solution. But, surprisingly, it's not working.
My LoungeActivity calls startServer() method of IWorker interface. Corresponding method of my WorkerService does some job and makes a callback - this works fine. Then WorkerService spawns a new thread and callback from this thread results in a bad Exception being thrown:
Can't create handler inside thread that has not called Looper.prepare()
Here's some code to make it clear:
startServer() implementation:
private void startServerImpl(String name, float latStart, float latEnd,
float lonStart, float lonEnd)
{
// some instructions here
// this works fine:
callback.notifySocketCreated();
// my naughty thread:
new ServerThread().start();
// some instructions here
}
ServerThread code:
private class ServerThread extends Thread {
#Override
public void run()
{
//some instructions here
// this call will cause an error
callback.notifyGameRegistered();
}
}
Every method from callback looks like that:
public void notifyGameRegistered() throws RemoteException
{
handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED));
}
In Handler's handleMessage() method I'm doing a simple switch(msg.what) and in every case there's a simple UI modification (showing a Toast, changing Text, etc.).
I have no idea why is this Exception thrown.. I've managed to fix it by packing code into a Runnable and calling runOnUiThread() but it still makes me curious - shouldn't a Handler always run in thread that created it? Or maybe I'm doing something wrong?
I know this is a bit late - but the problem is that you called dispatchMessage().
The correct method is sendMessage().
dispatchMessage() will call handleMessage() on the same thread.
I am guessing the problem is not your Handler being on the wrong thread - but that the UI is trying to create a Handler somewhere in yout onHandle() method. Because onHandle() is called on the wrong thread, you are getting an exception.
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg)
{
if (msg.callback != null) {
handleCallback(msg);
} else {
handleMessage(msg);
}
}
You have to somehow call the offending function from the main thread.
The function that changes the UI should be in the activity that owns the UI.
This link should help you out:
http://android-developers.blogspot.com/2009/05/painless-threading.html