Bring task to front on android.intent.action.USER_PRESENT
Here's a slightly hackish implementation that works for me:
-
Create a simple BringToFront activity that simply
finish()
itself on itsonCreate()
:public class BringToFront extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); finish(); } }
-
In your BroadcastReceiver, start the BringToFront activity above instead of your activity_A if the action is USER_PRESENT:
@Override public void onReceive(Context context, Intent intent) { Class<? extends Activity> activityClass = activity_A.class; if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) { activityClass = BringToFront.class; } Intent i = new Intent(context, activityClass); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); }
This works because the BringToFront activity has the same taskAffinity
as your activity_A and starting it will make the system bring the existing task to the foreground. The BringToFront activity then immediately exit, bringing the last activity on your task (activity_B in your scenario) to the front.
It's worth noting that on API level 11 (Honeycomb), a moveTaskToFront()
method is added to the system's ActivityManager service that might probably be the better way to achieve what you want.
celoftis
Updated on June 04, 2022Comments
-
celoftis almost 2 years
BACKGROUND
I have a task (i.e. app) with multiple activities.QUESTION
How do I bring a task to the front w/o re-ordering the activity stack for that task?USER SCENARIO
When the device boots (i.e. after android.intent.action.BOOT_COMPLETED broadcast is received) my app starts, call this task 1, and displays activity A (code below). As the user interacts with task 1, he/she opens activity B on the stack (activity B is now currently displayed on screen). Next the user taps the home key and opens some other task, call it task 2, then locks the screen. The user unlocks the screen, and the android.intent.action.USER_PRESENT intent is broadcast and received by my app (see manifest snippet below). My executes the startActivity() call in my IntentReceiver class as expected, but instead of just bringing the task to the foreground it creates a new task, call it task 3.CHANGES I'VE TRIED
If I modify or change the Intent.FLAG_ACTIVITY_NEW_TASK to any other intent then I get this error message:Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
...so it looks like I have to use Intent.FLAG_ACTIVITY_NEW_TASK.
If I change the main activity's lauchMode to "singleTask" the correct task is brought to the foreground (i.e. no new task is created), but the activity stack is reordered such that activity_A is on top of the stack.
At this point I am at a loss as to how to bring an existing task to the foreground w/o re-ordering the activity stack while listening for the android.intent.action.USER_PRESENT intent, any help would be appreciated.
BTW, This app is being delivered on to a group of employees, not the general public, on company owned android devices.
CODE SNIPPETS
To start the app I setup a broadcast receiver in my manifest file.<application : <activity android:label="@string/app_name" android:launchMode="singleTop" android:name=".activities.activity_A" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> : <receiver android:enabled="true" android:name=".utilities.IntentReceiver" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" > <intent-filter > <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.USER_PRESENT" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
In my IntentReceiver class, I start my main activity...
public class IntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent i = new Intent(context, activity_A.class); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } }
-
celoftis over 12 yearsThis works almost except in the following scenario: (1) The app is running; (2) user quits app (main activity calls finish()); (3) User locks screen; (4) user unlocks screen. In this scenario, the app receives the Intent.ACTION_USER_PRESENT (see my Log.i statements in logcat) so it starts and exits the BringToFront.class activity as expected, but since the app was previously exited, no other activities exist in the stack, and the user returns to the HOME screen (or whatever app was previously displayed). How do I know if the app is running so that I can start activity_A.class?
-
Prachur over 10 yearsYou saved my time Joe. Was searching for this for last two days. A nice workaround.
-
Pierre over 10 years@Joe Anything for Pre-Honeycomb?
-
Pierre over 10 years@celoftis Did you remember to de-register your BroadcastReceiver on exit?