0

I had Activity A(launchMode is singleTask) and B. In onCreate() of A, I triggered an alarm, which will activate a BroadcastReceiver after some time. Then I pressed home button to hide A.

In that BroadcastReceiver's onReceive(), following code will be executed:

Intent intent = new Intent(context, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

And then I found B was launched normally, but A will also be resumed. I don't know why and don't like that behavior.

Let's imagine: user opened you app's Activity A, pressed home button and opened another app's Activity B, then a BroadcastReceiver is activated and Activity C of your app is opened, user did some stuff there and then he pressed back button. He should see B instead of A, right?

How can I forbid this behavior? Thanks in advance.

ywwynm
  • 11,573
  • 7
  • 37
  • 53

3 Answers3

2

I found an appropriate solution by myself, again...

Add android:taskAffinity="hello.world"(Any string different from your app's package name and contains at least one point is good) for Activity A in AndroidManifest.xml.

Reason? When start an Activity with FLAG_ACTIVITY_NEW_TASK, it will check if there was a task existed with same taskAffinity. If yes, it won't create new task but will be pushed to that task directly. In our case, since we don't have android:taskAffinity="..." written, all Activities have same taskAffinity. As a result, when B is launched from BroadcastReceiver, it is added to default app task where A is existed in, too. I think, then the default app task will be activated and all Activities inside it are going to be pushed into top of back stack. Then we know the result: pressing back button in B will lead us to A.

Other behavior change? Yes. If using this method, B cannot have multiple instances unless launch it with one more flag: FLAG_ACTIVITY_MULTIPLE_TASK.

Interesting related discovery? Yes. I find that if pressing home button in A and launching B in BroadcastReceiver soon in 5 seconds, then B will display after a delay. But if B is launched after more seconds, it will display very quickly. This is a protection by Android system, for more details, you can reference Delay while launching activity from service. Trust me, this is very very inconspicuous but interesting(And no solution:).

ywwynm
  • 11,573
  • 7
  • 37
  • 53
0

I think you will need to add one more flag Intent.FLAG_ACTIVITY_NO_HISTORY.

Intent intent = new Intent(context, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(intent);

App's current behavior can be explained in this answer. As suggested in linked answer,

If your app is already running, Android will just launch the Activity into that task.

So extra flag Intent.FLAG_ACTIVITY_NO_HISTORY will help.


Edit

Based on discussion in comment, You can check if Your activity is in background or foreground (this can help) and depending upon result use Intent flag Intent.FLAG_ACTIVITY_CLEAR_TASK.

Community
  • 1
  • 1
Nakul
  • 1,313
  • 19
  • 26
  • It's an interesting flag while makes no difference. – ywwynm Nov 17 '16 at 01:22
  • I guess the problem is Activity is getting started in Already available TASK, what if you explicitly mentioned "Intent.FLAG_ACTIVITY_CLEAR_TASK"replacing "Intent.FLAG_ACTIVITY_NO_HISTORY". – Nakul Nov 17 '16 at 06:01
  • Yes, using `Intent.FLAG_ACTIVITY_CLEAR_TASK` helps. However, if we don't press home button in A and still launch B, then A will be destroyed because of that flag, which isn't perfect for me. – ywwynm Nov 17 '16 at 08:07
  • I thought about that just a few second after I saw `Intent.FLAG_ACTIVITY_CLEAR_TASK` and realized that it can help. However, I have many Activities and I think it's not elegant to judge if any of them are existed. But still thank you. – ywwynm Nov 17 '16 at 12:07
  • If possible let me know, what solution you implemented. – Nakul Nov 17 '16 at 13:28
  • please see my answer~ – ywwynm Nov 18 '16 at 02:29
0

Just add a line of setting in AndroidManifest.xml for B Activity.

android:launchMode="singleInstance"

Use the simplest way to start the B activity

context.startActivity(new Intent(context,B.class));

But this way has a problem,it will influence all places when B activity is started.