zoltish
zoltish

Reputation: 2312

Notification to resume activity (with data intact)

I've seen many questions in regards to this "issue" but there aren't any with an actual answer that works flawlessly.

In my app (fitness related) I issue a notification when the user leaves it during a workout so that he can quickly return to it.

Intent intent = new Intent(ctx, WorkoutActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.setClass(ctx, WorkoutActivity.class);
return new NotificationCompat.Builder(ctx)
            .setOngoing(true)
            .setAutoCancel(true)
            .setContentIntent(PendingIntent.getActivity(ctx, 0, intent, 0))
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setSmallIcon(icon);

Now this works just fine. Thanks to the Intent flags the activity is resumed if it's up and running.

However the problem I'm seeing is that whenever the app has been in the background long enough and the OS decides to kill it; entering it through the notification will start a new instance of the activity - losing all data. Here are the two ways of re-entering the app after it being in the background, including the behaviour I'm looking for.

  1. Press the notification. Problems arise here since the activity has been destroyed and the notification launches a new clean instance of it, without any data saved. This is my problem...
  2. Press the launcher icon. You are then taken to the main activity of the app, and upon closing this you are taken to the destroyed version of the activity and it is restarted, with all state restored. This is how I want it to work through the notification as well.

Additionally I am saving all state in onSaveInstanceState and restoring it as per android standard with the savedInstanceState variable in onCreate.

Here's the relevant part of the manifest:

  <activity
        android:name="workout.progression.ui.workout.WorkoutActivity"
        android:parentActivityName="workout.progression.ui.MainActivity"
        android:theme="@style/AppTheme.WorkoutActivity"
        android:windowSoftInputMode="adjustResize|stateAlwaysHidden"/>

And here's the root activity:

   <activity
    android:name="workout.progression.ui.MainActivity"
    android:label="@string/app_name"
    android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
     <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
         <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

Upvotes: 2

Views: 712

Answers (1)

Toguard
Toguard

Reputation: 447

There is no way to prevent an activity from being killed by the OS, however, you can persist that data onto something else like SharedPreferences, a Database or to a file. Here's a guide on how to persist data: Storage Options.

Alternately, you can use a different launch mode such as singleTask:

The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.

or singleInstance:

Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task.

This can however, mess a little with how your app and activity flow is handled.

References:
Storage Options
Activity Elements: Launch Modes

Upvotes: 1

Related Questions