Flurry onEvent() not sending in custom uncaught exception handler - android

I'm trying to use Flurry's onEvent method in my custom uncaught exception handler (UEH) but the events aren't showing up and I'm thinking that it might be because by the time it's gotten to the exception handler the flurry session has ended.
I make the call to FlurryAgent.onStartSession in the onStart() method of every activity and calling FlurryAgent.onEndSession() in the onStop() method of every activity.
I'm setting my UEH in my first activity:
Thread.setDefaultUncaughtExceptionHandler(new TopExceptionHandler(this));
My UEH (simplified) looks like:
public class TopExceptionHandler implements UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler defaultUEH;
private Activity app = null;
public int numberOfStories = -1;
public TopExceptionHandler(Activity app) {
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
this.app = app;
}
#Override
public void uncaughtException(Thread t, Throwable e) {
Map<String, String> params = new HashMap<String, String>();
ExceptionHandlerValues values = ExceptionHandlerValues.getExceptionHandlerValues();
params.put("model", values.model);
params.put("androidVersion", values.androidVersion);
params.put("androidSDK", values.androidSDK);
params.put("wattpadVersion", values.wattpadVersion);
params.put("misc", "StoryCount=" + values.storyCount + ";");
params.put("class", e.getClass().toString());
// Send it off to Flurry as an event
FlurryAgent.onEvent(ExceptionHandlerValues.EVENT_ID, params);
defaultUEH.uncaughtException(t, e);
}
}
If the flurry session has ended (which I'm kind of thinking it has) how can I start a new one in my UEH? I've seen other people say they've successfully implemented this solution so I know it's possible, but I can't seem to get it.
Thanks!

I ended up starting a new flurry session in my UEH using the application context. Events are now being sent and recorded which makes debugging problems our users are experiencing much easier.

Related

How to override handleUncaughtException without changing its functionallity

I asked this question some time back on Stackoverflow, the answer worked for me, It overrides thehandleUncaughtException, I save the exception and throws the default Unfortunately app has stopped working, but when i integrated this in my app, I am facing an issue.
This is the answer i got.
private Thread.UncaughtExceptionHandler defaultExceptionHandler;
public void registerCrash(){
defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException (Thread thread, Throwable e){
handleUncaughtException (thread, e);
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
}
});
}
What it does, first it goes to handleUncaughtException (thread, e); i save the crash log in this method, then it reads this line
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
here we throw uncaught exception again, so it goes to the first line again, and again saves the exception, and this goes in loop, and application becomes not responding.
What i want is to save crash log, and then show the default Unfortunate message to user.
EDIT
On Application launch it reads this;
defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
When application crashes, it reads these lines
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException (Thread thread, Throwable e){
handleUncaughtException (thread, e); //Custom Method
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
}
So it first goes to handleUncaughtException() there i have provided custom implementation, then it goes to this;
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
The defaultExceptionHandler is never null; So it goes in a loop in case of multiple crashes.
I have tried adding count there, but it was 0 each time.
The most likely explanation is that your registerCrash() method is being called twice.
The first time, you register Handler 1; there is no default handler at this point, so it sets defaultExceptionHandler to null. The second time, you register Handler 2, and then update defaultExceptionHandler to point to Handler 1.
On an uncaught exception, Handler 2 gets invoked first. It calls your custom handler method, then invokes defaultExceptionHandler, which now points to Handler 1.
Handler 1 gets invoked. It calls your custom handler method a second time, then it invokes defaultExceptionHandler, which now points to itself. This step repeats until your stack overflows.
I suggest two changes. First, add a guard to ensure you only register your crash handler once. Second, don't store the fallback handler in a field; capture it in a closure so the value seen by your handler never changes.
private static final AtomicBoolean CRASH_HANDLER_REGISTERED = new AtomicBoolean();
public void registerCrash() {
if (CRASH_HANDLER_REGISTERED.compareAndSet(false, true)) {
final Thread.UncaughtExceptionHandler defaultHandler =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e); // Custom Method
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, e);
}
}
}
);
}
}
I suggest you to try another approach, avoid overriding exceptions, catch it and retrive the error code, and do this:
when x code with x conditions verify, do that

How do I handle uncaught exceptions and then delegate handling back to the system?

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"
... />

Communication between Android Services and Activities

I want to develop an Android App with three activities and two services.
The first Service, named WebClientService, calls a REST API every 30 seconds, using an Handler, and has to notify the active Activity with the result.
It also has to notify a second Service, named DatabaseService, in order to update a local DB.
The Database Service will be called just once onCreate of the activity (in case of app crash and restart) and just once at onRestart (in this way we have data to show in case there were connectivity issues). The activities will then keep themselves updated thanks to the WebClientService that notifies the "alive" activity every 30 seconds.
Questions are:
What's the best way to notify for an update both the active activity and the background DatabaseService?
My idea is to use sendBroadcast() within WebClientService and a BroadcastReceiver in every activity and within the DatabaseService, is it the right approach?
Should I use the same approach for the communication between AllMeetingRoomActivity and DatabaseService or should I use a Bound Service?
Thanks
UPDATE:
DatabaseService won't be a background service anymore but just a shared instance of the db layer between WebClientService and the activities.
So question now is: is it a good approach to just write my 30 seconds updates to the local db and allow the activities to update themselves every few seconds simply reading from the local db?
Would that affect the performance too much?
Context:
Follows what I've implemented so far but using SettableFutures and thus needs to be re-implemented using Services and Broadcasts once I've clear how to make them communicate effectively:
public class MainActivity extends AppCompatActivity {
private TextView meetingsTextView;
private EditText mEdit, editSubject;
private final ConnectorInitializer clientInitializer = new ConnectorInitializer();
private AppConnector genericClient; // can use OutlookClient or a test client to talk with a mock server
#Override
protected void onCreate(Bundle savedInstanceState) {
// initializes client based on the settings in "config.json"
genericClient = clientInitializer.create(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
meetingsTextView = (TextView) findViewById(R.id.NowMeeting);
mEdit = (EditText)findViewById(R.id.editText);
editSubject = (EditText)findViewById(R.id.editSubject);
Futures.addCallback(genericClient.logon(this, scopes), new FutureCallback<Boolean>() {
#Override
public void onSuccess(Boolean result) {
Log.d("APP", "-- Logged in. --");
databaseConnector.synchronouslyGetBackupFromLocalDatabase() // FUTURE
// callback here
// onSuccess, onFailure
}
#Override
public void onFailure(#NonNull Throwable t) {
Log.e("\n ~~~~>> logon \n", t.getMessage());
meetingsTextView.setText(R.string.Login_Failed);
}
});
}
/** At the moment the UI is not updated automatically every 30 seconds
* but manually using a refresh button
*/
public void getBookings(#SuppressWarnings("UnusedParameters") View view){
Log.d("APP", "Retrieve button clicked: "+(DateTime.now())+". Calling async getCalendar.");
meetingsTextView.setText(R.string.retrieving_events);
try{
Futures.addCallback( genericClient.getCalendarEvents(), new FutureCallback<String>(){
#Override
public void onSuccess(final String resultCalendars) {
Log.d("APP", "Success. Result: "+resultCalendars);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d("APP", "Calendars SUCCESSFULLY retrieved.");
String meetingsRetrieved = getString(R.string.calendar)+resultCalendars;
meetingsTextView.setText(meetingsRetrieved);
Toast.makeText(getApplicationContext(), "Success!", Toast.LENGTH_LONG).show();
}
});
databaseConnector.asyncUpdateLocalDbWithResults(); // FUTURE
// callback here
// onSuccess, onFailure
}
#Override
public void onFailure(#NonNull Throwable t) {
Log.e( "APP", "Calendar error. Cause: "+t.getLocalizedMessage() );
String retrieveError = "Retrieve error. \n\n\n"+t.getLocalizedMessage();
meetingsTextView.setText(retrieveError);
Toast.makeText(getApplicationContext(), "Fail!", Toast.LENGTH_LONG).show();
}
});
}catch(Exception ex){
Log.e("APP","Something went wrong in your code. Cause:"+ex);
}
}
Best option ever:
Use LocalBroadcastManager. More reference here.
MyService.java:
private LocalBroadcastManager localBroadcastManager;
private final String SERVICE_RESULT = "com.service.result";
private final String SERVICE_MESSAGE = "com.service.message";
#Override
public void onCreate() {
super.onCreate();
// Other stuff
localBroadcastManager = LocalBroadcastManager.getInstance(this);
}
Add below method in service, whenever you want to update data from service to Activity, call method by passing Arguments.
private void sendResult(String message) {
Intent intent = new Intent(SERVICE_RESULT);
if(message != null)
intent.putExtra(SERVICE_MESSAGE, message);
localBroadcastManager.sendBroadcast(intent);
}
HomeActivity.java:
private BroadcastReceiver broadcastReceiver;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_home);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String s = intent.getStringExtra(MyService.SERVICE_MESSAGE);
// do something here.
}
};
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((broadcastReceiver),
new IntentFilter(MyService.SERVICE_RESULT));
}
#Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
super.onStop();
}
Hope this will help you.
I think your approach is ok with BroadCastReceiver. However, BroadCastReceiver should be used for a global purpose (like communicating between 2 applications). If you intend to use BroadCastReceiver for your app only, I prefer using LocalBroadcastManager instead. Using LocalBroadcastManager is faster and more security when it can be caught only by your app.
There's another way to communicate between your activitys and your services is using EventBus. It will be much easier than using BroadCastReceiver (especially in passing data between them).
Update: About your update question:
is it a good approach to just write my 30 seconds updates to the local db and allow the activities to update themselves every few seconds simply reading from the local db? --> Of course NO. You should let your activities update themselves when they need. When you update your local db, you should know that is there any changes or not. If there is any change, use LocalBroadcastmanager to notify your activity to update.
Would that affect the performance too much? --> Yes, that do. The db connection will take time to execute and it will block your UI in some cases. in that case, you should use a thread with ExecutorService for each execute (insert, update...). One more thing to consider is updating that frequently will drain your phone battery very, very fast.
You can bind the services to the activities and update your UI.
Or you can use libraries like Otto or EventBus to create a publisher/subscriber dependency and notify your activities everytime your services publish an update of information.
Use event bus for this communication. EventBus allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other). It is designed exclusively to replace traditional Java in-process event distribution using explicit registration.
There are a lot of them:
http://square.github.io/otto/
https://github.com/greenrobot/EventBus
This is an example of Otto usage:
Bus bus = new Bus();
bus.post(new AnswerAvailableEvent(42));
#Subscribe public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}
bus.register(this); // In order to receive events, a class instance needs to register with the bus.
To post from any thread (main or background), in you case a Service and receive events on the main thread:
public class MainThreadBus extends Bus {
private final Handler mHandler = new Handler(Looper.getMainLooper());
#Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
mHandler.post(new Runnable() {
#Override
public void run() {
MainThreadBus.super.post(event);
}
});
}
}

android - callback function for handling crashes

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?

Using Global Exception Handling on android

Is there a code example, or a tutorial on how to use the Thread.setDefaultUncaughtExceptionHandler method? Basically I'm trying to display a custom alert dialog, whenever an exception is thrown, in my application. Is it possible to do this? I know it's a little bit tricky to display something on the screen, if the exception is thrown in the UI thread but I don't know any work around for this.
Basic Example for someone who comes to this page with a solution :)
public class ChildActivity extends BaseActivity {
#SuppressWarnings("unused")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int a=1/0;
}
}
Class for handling error:
public class BaseActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("Alert","Lets See if it Works !!!");
}
});
}
}
Here's a variant of the answer by Mohit Sharma with the following improvements:
Doesn't cause the app/service to freeze after error handling
Lets Android do its normal error handling after your own
Code:
public class BaseActivity extends Activity {
#Override
public void onCreate() {
super.onCreate();
final Thread.UncaughtExceptionHandler oldHandler =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(
Thread paramThread,
Throwable paramThrowable
) {
//Do your own error handling here
if (oldHandler != null)
oldHandler.uncaughtException(
paramThread,
paramThrowable
); //Delegates to Android's error handling
else
System.exit(2); //Prevents the service/app from freezing
}
});
}
}
For those who just want to see exception details when your app crashes on device (in debug config). This is application class:
private Thread.UncaughtExceptionHandler oldHandler;
#Override
public void onCreate() {
super.onCreate();
if (!BuildConfig.DEBUG)
return;
oldHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
try {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
Intent intent = new Intent(Intent.ACTION_SEND);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_TEXT, sw.toString());
intent.setType("text/plain");
startActivity(intent);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
if (oldHandler != null)
oldHandler.uncaughtException(t, e);
else
System.exit(1);
}
});
}
It uses external app as your UI thread might not working anymore.
Keep in mind that the The RuntimePermission("setDefaultUncaughtExceptionHandler") is checked prior to setting the handler and make sure you cause the process to halt afterwards, by throwing an uncaught exception, as things could be in an uncertain state.
Do not display anything, indeed the UI thread might have been the one that crashed, do write a log and/or send the details to a server, instead. You might want to check out this question and its answers.
I just wanted to point out my experience so far. I am using the solution suggested by https://stackoverflow.com/a/26560727/2737240 to flush the exception into my log file before giving control to the default exception handler.
However, my structure looks like this:
BaseActivity
|
_______________________
| | |
Activity A Activity B Activity C
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e, defaultEH);
}
});
where handleUncaughtException(thread, e, defaultEH); writes to the log and hands the call over to the original UncaughtExceptionHandler.
So what happened by using this code was the following:
Activity A is instantiated
New Default Exception Handler (DEH) is now my log handler + the old DEH
Activity B is instantiated
New DEH is now my log handler + the old DEH (log handler + original DEH)
Activity C is instantiated
New DEH is now my log handler + the old DEH (log handler + log handler + original DEH)
So it's a chain growing infinitely causing two problems:
The specified custom code (in my case writing to the log file) will be called multiple times, which is not the desired action.
The reference of defaultEh is kept in the heap even after the activity has been finished, because it is used by the reference chain so the worst thing that could happen is an out of memory exception.
Therefore I added one more thing to finally make this work without issues:
private static boolean customExceptionHandlerAttached = false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!customExceptionHandlerAttached) {
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e, defaultEH);
}
});
customExceptionHandlerAttached = true;
}
}
With this solution we can make sure to:
add a custom exception handler for our desired action
ensure that this action is only triggered once
allowing garbage collector to dispose our activity completely by calling finish()
if you want use this library
https://github.com/selimtoksal/Android-Caught-Global-Exception-Library
create your TransferObject not all in your activities just use in Base activity

Categories

Resources