1

This is pretty elaborate, so I'll try and be as clear as possible. Currently, my application needs to reload some data when it is launched. I am loading this data in the onCreate/onRestart methods of my main activity. However, I need to be careful to not reload the data if the user never leaves the current task.

For instance, if I need to start the in-built Contacts application from my main activity to select a contact, then my main activity will pause/stop while I am selecting a new contact. When I return to my main activity, onRestart will be called. In this case, because I have never left the Application's task, I do not want to reload the data. This means some check needs to be included here to determine if the user has come straight back from the Contacts app without ever leaving it.

Otherwise, if the user exits the Contacts app while it was open and re-launched the app from the launcher menu (or recent apps list, etc) - I want to close the Contacts app and reload the data when the Main activity's onRestart method is called.

Is there a way to do this without using any user-frightening permissions (e.g. GET_TASKS). I have been stuck on this problem for a long time now so any help would be GREATLY appreciated :)

Tyvm, B. Campbell

Bradley Campbell
  • 9,298
  • 6
  • 37
  • 47
  • 1
    Using [contentproviders](http://developer.android.com/guide/topics/providers/content-providers.html) with [loaders](http://developer.android.com/guide/components/loaders.html) could help you. You don't need to manually reload data. –  Feb 12 '13 at 04:39
  • Hi, thanks for the response. My use-case is a little unusual, I know, but I only want to reload the data when the activity is being started (or restarted). ContentProviders are very useful tools, but not in this case. – Bradley Campbell Feb 12 '13 at 05:10
  • Also, I don't think code is necessary here. This is more of a is-this-possible and theoretically-how-would-you-do-it type question, rather than a here-is-my-code-can-you-fix-it type question. Although, I can put up some code if you think it may be of some help to you? – Bradley Campbell Feb 12 '13 at 05:13
  • Could you try [`getTaskId()`](http://developer.android.com/reference/android/app/Activity.html#getTaskId())? I used it for another purpose but I hope it could help you. The return value *will remain the same for the lifetime of the activity* (as the docs says). –  Feb 12 '13 at 13:38

2 Answers2

3

I learned a lot from the Android docs:

Tasks and Back Stack

Navigation with Back and Up

Application Structure

Here is some highlight:

A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the "back stack"), in the order in which each activity is opened.

When the current activity starts another, the new activity is pushed on the top of the stack and takes focus. The previous activity remains in the stack, but is stopped. When an activity stops, the system retains the current state of its user interface. When the user presses the Back button, the current activity is popped from the top of the stack (the activity is destroyed) and the previous activity resumes (the previous state of its UI is restored). Activities in the stack are never rearranged, only pushed and popped from the stack—pushed onto the stack when started by the current activity and popped off when the user leaves it using the Back button.

It means when your application pick up a contact, the activity stack in the task might be:

| Activity A in Contacts |

| Activity B in Your App |

| Activity C in other app|

When the user leaves a task by pressing the Home button, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack.

Even if the user exits the Contacts app while it was open and re-launched the app from the launcher menu or recent app list, the activity stack is still like the one we see above. The only possibility that may make your acitity start from another task is another app(might be a launcher app) that start the main activity in a new task by startActivity flags, which is a rare case. In this rare case, you can simply check the uid of the app who start your activity by Binder.getCallinguid() to differentiate it.

EDIT based on comments:

You may check if activity was opened from history by FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY:

if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0){

}else{

}

You can also look into:

android:excludeFromRecents if you don't want your app start from recent apps

android:finishOnTaskLaunch

android:stateNotNeeded

Community
  • 1
  • 1
StarPinkER
  • 14,081
  • 7
  • 55
  • 81
  • I believe you can override this behavior. For instance, since I want the Contacts app to only exist while it is in the foreground, I can start the Contacts activity by using the following code: Intent contactsIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); contactsIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); getActivity().startActivityForResult(contactsIntent, 1234); This would mean that when I resume my Task, the user would see my Activity immediately instead of the seeing the Contacts activity as per your example. – Bradley Campbell Feb 12 '13 at 05:22
  • Then why you make it no history? – StarPinkER Feb 12 '13 at 05:27
  • lol, I wonder this too. As per the specs I have to follow, when the user starts the app from the launcher (or recent apps list), then the main activity needs to be shown first and the data needs to load. In this case, I cannot show the contacts activity – Bradley Campbell Feb 12 '13 at 05:30
  • 1
    Then I think the [FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET](http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) is what you really want. – StarPinkER Feb 12 '13 at 05:33
  • Yeah, I had read about that earlier. It pretty much describes exactly what I want using some email example. However, if you return to the app using the 'Recent Apps' list, unfortunately, it doesn't work. It just shows the Contacts app as if nothing had happened. – Bradley Campbell Feb 12 '13 at 05:45
  • I just tested that, and FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET does not work (someone else had this problem http://stackoverflow.com/questions/8733634/flag-activity-launched-from-history-isnt-set-for-intents-from-history). By default, it seems to just open the same Activity, so if it wasn't originally opened by the recent tasks list, then it never will be. I have even tried setting the application to launchMode:singleTask, which should create a new intent every time the app starts - however onNewIntent is not fired when returning from to the app from the Recent Apps list. – Bradley Campbell Feb 12 '13 at 07:49
  • You mean the FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY doesn't work? I tested on my phone, it works. IceCream Sandwich, Samsung Galaxy S. – StarPinkER Feb 12 '13 at 07:57
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/24361/discussion-between-jermaine-xu-and-grandstaish) – StarPinkER Feb 12 '13 at 07:57
1

If the data you are loading related to the application life-cycle not to a specific activity, you can load it in application class, so it will not be reloaded again unless your application task is killed.

iTech
  • 18,192
  • 4
  • 57
  • 80
  • In this case it is Activity-specific. I think I was a little confusing before, I have edited it a bit now, hopefully it is slightly more sensical. Basically I want to reload the data every time I start the Activity, except for when I am starting another Activity for a result and returning directly from that activity (i.e. by directly, i mean they never exited that 2nd Activity) – Bradley Campbell Feb 12 '13 at 04:55