I perform some app global initialization in my Application's OnCreate (a subclass of Application). In some rare occasions this initialization fails. When that happens I used to show an activity with a failure message, but apparently this was a bad idea since this function also being called before my background Service is started, which then launches this "failure" activity out of nowhere.
My current solution is to mark with some flag that the initialization failed, and check it in every activity (or Service) that the app might start with. This solution is also bad, because it requires me to remember to check it in every new component I add (that can be launched).
Does someone have a better idea?
If Application initialization fails, you're screwed. Throw an exception and give up.
As corollaries:
Keep the Application init as thin as possible - do as little as possible.
Avoid doing anything that can fail.
Postpone operations that can fail to a point where you have more options for recovery, such as an Activity's lifecycle.
If you need help with a specific failure, please include it in your question.
Related
In the app I have an activity which has launch mode as singleTask. There are number of use cases which pass through this activity and hence it's called number of times. On stress testing the app by running monkeyrunner script and calling this activity every few seconds causes ANR's.
I guess, the way it's designed where most of the use cases pass through this activity is not correct but I am not in a position to change this design.
Is there anyway ANR's can be suppressed? I mean, adding UI operations to event queue so that it doesn't block main UI thread and doesn't give ANR.
It is unclear from the question what your activity is (or should be) doing. Probably you need a service instead.
It is common to perform time-consuming operations in background threads and deliver the results to the UI thread.
You may use the classes Handler/Looper (it it easir to send Runnables rather than messages), or use an AsyncTask. The AsyncTask is nevertheless tricky, this is discussed here: Is AsyncTask really conceptually flawed or am I just missing something? . AFAIK Google tried to fix the typical bugs and made the new behavior incompatible with the old one (namely, I have seen some misbehavior on the newer Androids that may be explained by the assumption that since some version threads doing asynctask jobs get killed after the activity that started them goes out of the screen).
I can guess that singleTask is your way to fight the fact that an activity dies when the screen turns, and a new one comes. I suggest you use singletons (they survive screen rotation but do not survive a process restart, one more thing that sometimes happens in Android). (The user switches to an app like Camera, takes a big photo, returns back -- and the activity is restarted because Camera needed memory. Have seen this in practice, but that time I did not try to find out if the whole process was restarted.)
Anyway, please add logging telling you when your activity in entered and left, including onNewIntent() and other lifecycle functions (to be on the safe side, I recommend to print the thread names as well). Then you will probably see what is going on.
An application background service updates sqlite database. Therefore my activities are becoming outdated. Activity intents also contain outdated params so onCreate, onResume will crash the application. An easiest solution is to restart whole application. I don't want to add IFs to all onCreate, onResume methods in all activities to handle one special case.
I noticed that ACRA has following code executed after an exception has been handled.
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
However many people discourage use of System.exit(0). Is System.exit(0) really that dangerous for an Android application data integrity? Of course my code will close the database before existing.
Update:
I known how to use finish(), content providers, send broadcasts, read many answers here on SO, etc. However each of these approaches requires additional thousands lines of code. I implemented solution with System.exit(0) in ten minutes. The restart is so fast that it is indistinguishable from ordinary startActivity action. The db update/restart is done after longer user inactivity so the app is already suspended by the system. My app doesn't require real time syncing. During tests the application behaves correctly. This is quick and dirty solution.
Therefore I asked the question about possible side effects of System.exit(0). Not how I can do the design differently. I know that current design is not perfect.
System.exit(0) is an artifact from Java runtime, it isn't meant for Android. So in any cases using it would be worst solution.
Why don't you use Activity.finish() gracefully?
If you terminate the process you are living in, you'll loose most of the caching and restart time (~resume in the eyes of the user) for it next time will be higher.
Read more in Activity Lifecycle documentation on Android Developers.
Killing the process will not clean up any registered resources from outside the process. BroadcastReceivers, for example. This is a leak and the device will tell you as much.
You really shouldn't be updating the database schema from a background service. Do it when your activities resume.
If you are just updating your data, resuming an activity should validate the data specified by the Intent and tell the user if, for example, Item X is no longer there.
No tool is that dangerous if used carefully and for a specific, well thought off purpose.
However, In your case I do not believe System.exit() is the right way to go. If your application depends on data from a database, create a background service (or a few, depending on what you need) that will inform your application of changes and update the data. It is, in my opinion the right way to handle changes.
As for scenarios when you want to use System.exit() I personally sometimes use it when I can't recover from a critical error and no graceful degradation is possible. In those cases it is better to force all resources associated with your application to cease rather than just leave loose ends tangling around. To clarify, you should always use error handling before doing anything radical. Proper error handling is often the way to go.
But this is a very delicate topic and you are likely to receive quite a few diverging answers.
Therefore my activities are becoming outdated.
Use a ContentProvider and ContentObserver (or the Loader framework), or use a message bus (LocalBroadcastManager, Otto, etc.) to update the activities in situ.
Activity intents also contain outdated params so onCreate, onResume will crash the application
Copy the relevant "params" to data members of the activities. Update those data members as needed (e.g., from the handlers from the message bus-raised events). Hold onto that data as part of your instance state for configuration change (e.g., onSaveInstanceState()). Use this data from onCreate(), onResume(), etc.
An easiest solution is to restart whole application
It is not easiest, if you value your users, as your users will not appreciate your app spontaneously evaporating while they are using it. Do you think that Gmail crashes their own app every time an email comes in?
Next, you will propose writing a Web app that uses some exploit to crash the browser, because you cannot figure out how to update a Web page.
I noticed that ACRA has following code executed after an exception has been handled.
A top-level exception handler is about the only sensible place to have this sort of code, and even there, the objective is for this code to never run (i.e., do not have an unhandled exception).
There's an existing answer HERE that might give you some help as to why people say it's bad to use System.Exit().
Hiii i am testing a test method in which i want after a pressing a button my activity should alive so that i can see next test cases in that activity,but unfortunately my activity get killed after running the test case .is there any way to keep the activity alive.if there code line please let me inform.
I cannot be sure without seeing your code, but i am guessing either in the testcase, or the setup() and tearDown() methods you are going to have to been calling a method such as finishOpenedActivities() which closes all the activities you have open. removing this line will keep the activity open.
Having said that it is typically best practice to have your test cases start from a clean state because having test cases that rely on ordering means that if one fails all the others fail even if that functionality does work plus you have to do slightly hacky things in order to get them to all run in the order you want.
I dug into the source code a bit and found that the tearDown() method, as implemented in ActivityInstrumentationTestCase2, will make a call to finish() on your current activity. So even if you don't explicitly finish() you Activity in your implementation of this method, it will be done when calling super. However, per the source code documentation: removing the call to super in tearDown() can cause a memory leak if you have a non-static inner class, and, perhaps more importantly for your case, the running Activity seems to still be killed once the test is completed. Even if you have an empty implementation of tearDown(), it seems as though the Activity Under Test gets finished at the end of the run. As of right now, I don't know of a way to avoid this.
As an alternative based on your comment for #Paul Harris's answer, Robotium has many methods that allow you to wait for something to happen. You may want to look into waitForText() or waitForView(), which can take a timeout as a argument, to have Robotium pause while your button click is performing some action. Hope this helps!
I want to know when the app is closed, because I need to erase a Database when the user shutdown the app, just in the moment when the user close the app is the right moment to erase the SQLite Database, how can I detect this?
This is a flawed design idea, which reflects a misunderstanding of the system - when the process overall dies, it's dead, meaning your code is no longer running.
You can do some tracking and have the last onDestory()'d activity do the cleanup as a courtesy, but don't assume that it will always actually happen (the method is not always called). If having a stale copy is a problem, clean it up on the next run.
That said, you can try using the ndk to provide a handler for process termination signals, but still I wouldn't count on it working in all cases. The limited potential to gain any sound functionality from this would probably not justify the effort unless you are already familiar with the concepts involved.
And do not for a minute mistake cleaning up for a security mechanism, as the file is there while your app is running, and would remain if your app terminated in an unexpected way.
Supposing you don't finish() your main activity, clearing your database inside the onDestroy() method of that activity might be the closest of what you want to accomplish. As has been pointed in the comments, refer to http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle.
I have a multi-Threaded android application. One of the things my application does is saves various data to a database on a server via webservices. I was trying to figure out why things were not saving to the server correctly, and saw in one of my log files, that the application objects onCreate() method and constructor were called in the middle of one of the requests going up to the server. These request are in the background and are sent via an intentservice.
I have my application set to catch unhandled exceptions and log them, and I did not see anthing in there. The application onCreate() and constructor was called, the application was kicked back to the main/first screen, the user then had to re-login, and it seems that the database was wiped(which is something else I am wondering about).
So, my main questions are: Why did the application object onCreate() and Constructor get called(why did the application get killed), why did the database get wiped when the above happened because if I do a force stop from inside of settings, applications, it never kills my db.
two words: low memory
I have the same problem. No solution for now. Try to take advantage of the onLowMemory() method, maybe the OS will spare your app.
My application object gets restarted randomly (not any time) when I am coming back from an external application (ex. camera or gallery) for onActivityResult().
Hope that helps someone.
If the application is not a service, but a 'normal' application that calles your intentservice, it is subject to the normal application lifecycle: this means it will get killed when in the background.
Look for the explaining image on this site: http://developer.android.com/guide/topics/fundamentals/activities.html
Take note of the red "Process is killed" part on the left, an the subsequent "onCreate()" afterwards.
I've actually seen very similar behaviour that was caused by a NumberFormater trying to parse a null String. After the call to parse(), the application simply reset itself back to the splash screen with no errors at all. Wasn't fun to track down, pretty much stepped through half the code base trying to find out what was happening - the debugger disconnected and the app restarted when stepping past the parse call.