How start different activity (and recover state) if service is running?

Viewed 263

I've got a fairly complete location tracking app, but one problem is still bugging me. When launched, the app needs to display the second activity if the tracking service is currently running.

  • I have 2 activities (LoginActivity and MainActivity) and 2 services (LocationService and ReportingService - both run in their own processes).
  • When the app is tracking location, the 2 services must remain alive, but MainActivity can be killed.
  • LocationService creates an unremovable notification to ensure the user knows they're being tracked. When the user taps the notification, it will restart/create MainActivity - the intent has extras containing all the relevant data that MainActivity needs (the Accounts and Assets they have access to, and which ones are selected).

However, if the app is tracking and MainActivity has been killed and then the user opens the app via the regular launcher icon, they're taken to LoginActivity. LoginActivity is the typical entry point for the app, as defined in the manifest:

<intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

How can I have MainActivity be used as an alternate entry point if LocationService is currently tracking? How should it recover its previous state data?

  • Do I need to add some special logic to LoginActivity's onCreate() to check the running services and then immediately launch MainActivity?
  • If I do something like that, I then have another problem: there would be no state data for MainActivity. Is there a way to access the notification's intent if the user doesn't open it via the notification?
  • MainActivity.onSaveInstanceState() saves the state data to a bundle, but I think that that's gone after the activity is killed, isn't it?
  • I have considered saving the state data directly to SharedPreferences, but this feels undesirably hacky. My "thing" objects all implement Parcelable so they can be put in bundles and intent extras, but you can't put Parcelables in SharedPreferences. I could hack around this by JSONifying them, but the JSON representations of the objects were only intended for communicating with the RESTful servers, so they don't include some app-specific data. I dislike dirty hacks so I'd rather do this the right way.

Steps I think would be required:

  1. When tracking starts, MainActivity stores the DB IDs of the Accounts and Assets in SharedPreferences
  2. When LoginActivity is created, check whether LocationService is running
  3. If so, launch MainActivity with a special "restore from SharedPreferences" extra
  4. MainActivity.onCreate() displays a loading dialog and gets the DB IDs from SharedPreferences
  5. Broadcast to ReportingService that we need to fetch the objects corresponding to the DB IDs
  6. Listen for response, then update the UI and cancel the loading dialog

What's the best way to approach these problems?

2 Answers
Related