Ошибка: onNewIntent не вызывается для singleTop-активности с Intent.FLAG_ACTIVITY_NEW_TASK

В startActivity появляется ошибка.

Установив действия singleTop с различными taskAffinity в AndroidManifest.xml и используя Intent.FLAG_ACTIVITY_NEW_TASK при вызове startActivity, два действия могут быть созданы в двух задачах (по одному действию на задачу).

Вызов startActivity снова вернется к первому действию/задаче и вызывается onNewIntent. Однако при вызове startActivity четвертое время вернется ко второму действию/задаче, но onNewIntent не вызывается.

Единственное различие между двумя задачами - их taskAffinity. Так или иначе, наблюдается асимметричное поведение.

Однако, если используется Intent.FLAG_ACTIVITY_SINGLE_TOP, тогда onNewIntent вызывается как ожидалось.

Похоже, что singleTop в AndroidManifest.xml не совпадает с Intent.FLAG_ACTIVITY_SINGLE_TOP в 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> 

Ответы

Ответ 1

это немного поздно, но так как я только что наткнулся на это - как отмечает Мэтт, активность одного флага в манифесте и в намерении не совпадают (по крайней мере, в предыдущих версиях андроида).

в startActivityUncheckedLocked:

на пряниках - https://github.com/android/platform_frameworks_base/blob/gingerbread/services/java/com/android/server/am/ActivityStack.java

Посмотрите на строку 2204 -

 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                                && taskTop.realActivity.equals(r.realActivity)) {

поэтому он просто проверяет флаги запуска на намерение и не проверяет манифест. сравните это с выпуском jellybean mr1:

https://github.com/android/platform_frameworks_base/blob/jb-mr1-release/services/java/com/android/server/am/ActivityStack.java

посмотрите строку 2835 -

                if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
                        && taskTop.realActivity.equals(r.realActivity)) {

поэтому кажется, что в mr1 они проверяют r.launchMode(предположительно значение AndroidManifest.xml) в дополнение к launchFlags (предположительно самого намерения), тогда как в более старых версиях они проверяли только флаги намерения.

это было фактически зафиксировано 16 февраля 2012 года в этой фиксации: https://github.com/android/platform_frameworks_base/commit/f363dfd26c304bca33f12065a9ed3de291193962

короткая версия - установить единственный верхний флаг как в намерении, так и в манифесте.

(благодаря этому комментарию связанная ошибка в трекере ошибок Android, указав мне, в какой исходный файл посмотреть - http://code.google.com/p/android/issues/detail?id=4155#c9).