I read a lot about using Toast or Log and putting them into Thread.setDefaultUncaughtExceptionHandler(...).
But I just can't get ALL exceptions displayed.
Please tell me (or point me to a resource) where it is described how to to it.
With working examples, when possible.
Thank you.
My guess is: when certain things go wrong (some global exception which destroys the whole app), toasts can't be displayed anymore.
If you are just developing don't try to use Toasts to display exceptions just work with Log.e() and the other Log functions it will all get displayed in LogCat you won't loose any exceptions. If you want to notify the UI that an Exception happened do it with a BroadcastReciever. So you have the place where you catch the Exception that fires an Intent which contains the message as an extra and in your Activity you just have to
registerReceiver(receiver, new IntentFilter("SOME_STRING_IDENTIFYING_THE_INTENT"));
Make sure you unregister the Receiver in the Activities onPause method.
The BroadcastReciever has a onReceive method that you can use to fire of the Toast.
Related
There are some peculiarities on android that i hate like a hell...
The issues around isFinishing() of activity are the worst.
I do understand some actions are not allowed after or during this process, but the only way we have to check it is by this method, and somethimes it isn't effective let me show a very simple example and please guide me in how to solve it with the best practices:
I want to add a fragment to my screen
if(!this.isFinishing() && getSupportFragmentManager().findFragmentByTag(VerifyIdentityDialog.CHALLENGE_DIALOG_TAG) == null)
try {
new VerifyIdentityDialog((ChallengeRequiredException) e, new DefaultVerifyIdentityListener())
.show(getSupportFragmentManager(), VerifyIdentityDialog.CHALLENGE_DIALOG_TAG);
} catch (Exception e1) {
Crashlytics.logException(e1);
}
This code is running only on MainThread it explicitly checks if the activity is finishing before try but still i get around 2% of users running into exception on it...
The exception is:
java.lang.IllegalStateException
Can not perform this action after onSaveInstanceState
[Avoid pasting long stack trace since it is a default android exception and the related code is mentioned above]
1- Before i added !this.isFinishing() in the if, the exception was way more frequent, but still didn't solve it 100%
2- according to Crashlytics 97% are on background when it hapens, so I THINK the code starts, the user goes to background then it simple crashes
the question is...
how is the proper way to solve it... i hate catching exception for predictable situations
You can directly check whether the FragmentManager has saved its state via isStateSaved() - you should only show() your dialog if the state is not saved.
I am getting an error as Null pointer exception and unable to instantiate activity when I am creating a toast in activity constructor.I want to know the reason why toasts are working in onCreate method but not in activity constructor
The OS is responsible for constructing your Activity classes. This is because it needs to perform some setup, including providing the Activity a proper base Context. Without this, you cannot make Toasts.
In general, you should avoid doing anything in the constructor of an Activity (and you should definitely not be making instances of them yourself using new).
Usually a Toast appears as a feedback to user input (say a button click) or when some external event is registerd (say a network error happend or new incoming data is available).
However, to me it sounds as though you want to show a Toast right after opening your activity, is that correct? Then you should put it in the onCreate method of your activity. An example Toast is made like this
Toast.makeText(MainActivity.this, "Hello World", Toast.LENGTH_LONG).show();
You might also consider putting this call in the onResume method. I recommend getting familiar with activity lifecycles.
Instead of using Toasts you might also want to check out Snackbars.
I've inherited a project and I don't understand how to either get a response, or set a callback from the following code:
startService(new Intent(this, VenueUpdateService.class));
At the moment the application continues even if the VenueUpdateService fails. I want to change it so that the application waits for a success/fail from VenueUpdateService.
I get a response within the VenueUpdateService class about success/fail. But how do I pass this back to the activity that started the service?
Thanks,
James.
What you're asking to do seems kind of strange to me. A Service will always succeed in being started if you call startService. It's not as if startService is some risky behavior that needs be wrapped in a try/call block.
But I suppose your Activity could register a BroadcastReceiver that receives a broadcast sent from the service in onStartCommand.
Or maybe you're looking to bind to the service, in which case you'll know when you're bound. see here
What I did was change the IntentService to an AsyncTask.
I basically wanted to stop the user interacting with the app while the VenueUpdateService did it's thing as it had to succeed at least once before the user could continue using the app.
So now I have:
VenueUpdateTask task = new VenueUpdateTask();
task.execute(response);
Within that class I show a progress dialog, do update venues.
My app may launch a sub-activity for a specific purpose. When that activity finishes, I get the results in onActivityResult. These results are then processed in the subsequent onResume. This consists of a setContentView and also starting an AsyncTask that puts up a ProgressDialog.
This all works well when initiated the normal way, which is via a user request (i.e., menu selection) after the app is up and running. However, under some conditions I need to do this right as the app is starting up, so I initiate this sequence right from my onCreate. What then happens is that I get fatal ResourceNotFound errors within any o/s call that implicitly calls the layout inflater. I got around this with setContentView by pre-inflating the view in my onCreate method, but the AsyncTask's onPreExecute still fails on ProgressDialog.show() as it "fails to find" Android's own progress_dialog.xml!
Anyone know what's happening here?
I suspect it's something to do with the timing, where this is occurring before the main activity has even had a chance to display its screen. These calls are all being made on the main UI thread, but maybe something hasn't completed within the o/s under these conditions.
As a closeout, the problem turned out to be totally unrelated to what I described in my post. Turns out it was due to blindly using some code that had been posted in some online forum showing how to get and use AssetManager. Trouble is, at the end of the block of code he had put "assMan.close()". Well, this closes the asset manager for the entire activity and resources can no longer be accessed!
It took a while to find it since it was not something that I did via my own understanding.
How i can display custom error message before foreclose or Application not responding message will happen for an application.
Or
Can i display Custom message like "Please wait....." instead of Application not responding message.
Thank you
You have to make sure you are handling any exceptions that are thrown. That is what causes a force close, an uncaught exception. as for the "not responding" message, again, this is up to the developer. You need to spawn new threads and do async tasks, that way processing does not block the main thread, which is what the UI runs on. When the main thread is blocked, that is when the "not responding" message happens. If you spawn a new thread, then you can display what ever kind of message you want to the user to notify them that something is processing.
I'll add to Ryan's answer that you can handle all critical exceptions without the need to wrap most of your code in try-catch. There is a beautiful method for that: Thread.setDefaultUncaughtExceptionHandler. It is mainly useful for bug reporting. For the purpose of showing a message you have to set the handler in Application.onCreate (you'll have to set <application>'s android:name in the manifest to your custom Application class), save the application context and then use it to show a notification in the status bar - it remains after your application has been force closed. Also, in order to have the Force Close dialog appear instead of just freezing after your exception handler has worked, you should call defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); in the handler's constructor and then in the end of public void uncaughtException(...) call defaultHandler.uncaughtException(thread, ex);.