When creating android applications, that are not trivial, it is important to keep in mind that android activities, widgets, and services have somewhat autonomous lifecycles that are controlled by the operating system itself. This is profound impacts on how you have to think about applications, since they are no longer something unified, and instead are a lot of different parts that are being orchestrated somewhat randomly. For example, an application’s process can be terminated anytime, or its activities can be terminated, or its services can be restarted. If you do not plan for such diversity in lifecycle states when building each widget service or activity, you will have a really tough time syncing them all up in the final application.
What is the right way
It is best not to think of the application as one monolithic unified chunk of code. It is really difficult to think of the application in terms of the Linux process or its constituent activities, widgets and services. There are so many moving parts and pieces, it is easy to get disoriented in the mix of these things, especially when it comes to keeping track of lifecycle states. A simple example of this is the tendency of standard activities to restart when the screen orientation is changed. If you are not planning for this from the get go, here you have a very nasty surprise the first time the user changes the screen orientation. Especially if you are keeping state information in the scope of the activity object! This can be disabled in the android manifest, but it sets the stage for how you have to think differently about applications.
So what is the right way? It is best to keep state information persisted, along major checkpoints in the code. This means that you have to constantly save pertinent information to some service persistent store, whether to file or the database, it does not matter. As long as information is stored, you can have some hope of reconstituting the last known state of an activity, service, widget. So you have to make sure when these activities services or widgets are reconstituted that you check for any pre-existing stored state information. This will ensure that your applications can restart from failure (unintended or intended).
In your service, make sure to keep track of all pertinent state information and save key information to persistent storage. This should be done when major state changes occur. Activities and widgets will also need to interact with your service. So it is really important to restore state on failure (and sense whether a start is clean or is a restart from failure). This will ensure that even if the service is restarted, any activities and widgets that rely on it will function moving forwards. For example, if your service was running a long-running task, before it got terminated, then on restart, it must ensure that that long-running task can be resumed, or restarted. Either ways any dependent widgets are activities would have to query the service to determine their initial state when they first bind to it. Alternatively, if you do not want to query the initial state, you can have the widgets and activities store their key pertinent state information to persistence as well.
When activity launches, and it depends on the service, it should start the service and bind to it. If the service was restarted unexpectedly and the activities not aware, it is best to have the activity query the service to figure out the initial state that should be set in the activity itself. Alternatively, the activity can store its own state information and restore it on startup. So if the activity kicks off some long-running process, it is best to store this state information to persistence. This way if the activity is restarted for whatever reason, it can pick up where it left off.
The key to all of this, is to make sure that key pertinent state information is persisted by an activity or service as it progresses through its lifecycle. You can implement complicated syncing between an activity and the service, to ensure that they are in the correct state at startup, but it might just be easier for each of the parties involved to store this information separately and restore it independently on startup or restart (and detect if start is clean or is a restart from failure). This way, you can create applications that are resilient to process terminations, service restarts, and even device restarts.