There appears to be a bug in startActivity
.
By setting activities to be singleTop
with different taskAffinity
in AndroidManifest.xml and using the Intent.FLAG_ACTIVITY_NEW_TASK
when calling startActivity
, two activities can be created in two tasks (one activity per task).
Calling startActivity
again will return to the first activity/task and onNewIntent
is called. However, calling startActivity
a forth time will return to the second activity/task, but onNewIntent
is not called.
The only difference between the two tasks is their taskAffinity
. Somehow, asymmetrical behaviour is observed.
However, if the Intent.FLAG_ACTIVITY_SINGLE_TOP
is also used, then onNewIntent
is called as expected.
It would appear that singleTop
in AndroidManifest.xml is not the same as Intent.FLAG_ACTIVITY_SINGLE_TOP
in the Intent
.
public class ActivityA extends Activity implements OnClickListener { private String tag; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); tag = getClass().getName(); Log.v(tag, "onCreate()"); setContentView(R.layout.main); Button button = (Button)findViewById(R.id.button); button.setText(tag.endsWith("ActivityA") ? "Activity B" : "Activity A"); button.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent; int flags = Intent.FLAG_ACTIVITY_NEW_TASK // | Intent.FLAG_ACTIVITY_SINGLE_TOP ; Log.v(tag, "onClick()"); intent = new Intent(this, tag.endsWith("ActivityA") ? ActivityB.class : ActivityA.class); intent.setFlags(flags); startActivity(intent); } @Override protected void onNewIntent(Intent intent) { Log.v(tag, "onNewIntent()"); } }
public class ActivityB extends ActivityA { }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".ActivityA" android:launchMode="singleTop" android:label="Activity A"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ActivityB" android:launchMode="singleTop" android:label="Activity B" android:taskAffinity="activity.B"> </activity> </application> </manifest>
this is a little bit late, but since i just came across this - as Matt mentions, the flag activity single top in the manifest and in the intent are not the same (at least on previous versions of android).
in startActivityUncheckedLocked
method:
on gingerbread - https://github.com/android/platform_frameworks_base/blob/gingerbread/services/java/com/android/server/am/ActivityStack.java
look at line 2204 --
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
&& taskTop.realActivity.equals(r.realActivity)) {
so it's just checking the launch flags on the intent, and not checking the manifest. compare this to jellybean mr1 release:
https://github.com/android/platform_frameworks_base/blob/jb-mr1-release/services/java/com/android/server/am/ActivityStack.java
look at line 2835 --
if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
&& taskTop.realActivity.equals(r.realActivity)) {
so it seems that in mr1, they are checking r.launchMode (presumably the AndroidManifest.xml
value) in addition to the launchFlags
(presumably of the intent itself), whereas in the older versions, they were only checking the intent flags.
it was actually fixed on february 16th, 2012, in this commit: https://github.com/android/platform_frameworks_base/commit/f363dfd26c304bca33f12065a9ed3de291193962
short version is - set the single top flag in both the intent and in the manifest.
(thanks to this comment on the associated bug in the android bug tracker for pointing me to which source file to look in - http://code.google.com/p/android/issues/detail?id=4155#c9).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With