Android-активность не запускается, если уже в бэкстеке в качестве рута? - PullRequest
3 голосов
/ 05 июня 2019

У меня есть пример приложения с 3 действиями: Main, A и B. Ни у одного из них нет режима запуска.

Теперь я делаю это:

  1. , откройте приложение, Mainактивность отображается
  2. покиньте приложение с помощью кнопки «назад», чтобы не выполнять никаких действий.
  3. получает широковещательную рассылку, которая запускает новое действие A (флаг new_task)
  4. открыть действиеB, нажав кнопку в задании A (без флагов)
  5. получить широковещательную рассылку, в которой начинается новое действие A (флаг new_task)
  6. новое действие A не началось (если я вернусь, то все еще будет предыдущее задание A)

На шаге 6 должно быть представлено задание A, но его нет.

Если явместо этого попробуйте представить действие C (в # 5), оно будет отображаться, как и ожидалось.

Если в # 2 вместо этого я оставляю приложение с помощью кнопки home, все работает как положено.

Как это возможно?И как я могу гарантировать, что действие всегда представлено? Я мог бы использовать FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP, но я хочу сохранить backstack.

ОБНОВЛЕНИЕ - ИСТОЧНИК: Вы можете посмотреть на источник , но я использую Xamarin (который в основном является родным Android, написанным на C #, очень похожим на Java).Это содержимое встроенного манифеста (убрал материал Xamarin):

<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="28" android:compileSdkVersionCodename="9" package="com.companyname.StartTest" platformBuildVersionCode="28" platformBuildVersionName="9">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application android:allowBackup="true" android:debuggable="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name="android.app.Application" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
        <activity android:label="A" android:name="A"/>
        <activity android:label="B" android:name="B"/>
        <activity android:label="@string/app_name" android:name="MainActivity" android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <receiver android:name="Receiver"/>
    </application>
</manifest>

Ответы [ 2 ]

1 голос
/ 15 июня 2019

Хорошо, давайте посмотрим на это согласно последовательности операций.

  1. откройте приложение, отображается основное действие

    Состояние backstack: Main Activity (root)

  2. выйти из приложения с помощью кнопки «назад», чтобы не выполнять никаких действий

    Состояние backstack: <No activity present as back was pressed>

  3. принятьтрансляция, которая запускает новое действие A (флаг new_task)

    Статус backstack: ActivityA (root)

  4. открыть действие B, нажав на кнопку в действии A (нетфлаги)

    Статус backstack: ActivityA (root) -> ActivityB (top)

  5. принять трансляцию, которая начинает новое действие A (флаг new_task)

    Статус backstack:ActivityA (root) -> ActivityB (top)

    Здесь Actvitity A не запускается, потому что он был запущен с флагом намерения 'FLAG_ACTIVITY_NEW_TASK', который имеет следующую документацию:

При использовании этого флага, если задача уже запущена для действия, которое вы сейчас запускаете, тогда новое действие будетне начнется;вместо этого текущее задание будет просто выведено на переднюю часть экрана в том состоянии, в котором оно было последним.

новое действие A не запускается (если я вернусь, все еще есть предыдущее действие A)

На шаге № 6 должно быть представлено действие A, но это не так.

Таким образом, текущая задача выглядит следующим образом ActivityA (root) -> ActivityB(top), ActivityA уже присутствует в задаче, и поэтому задача в целом только что выведена на фронт , чтоозначает, что ActivityB все еще находится наверху задачи.

Если я попытаюсь вместо этого представить действие C (в # 5), оно будет отображаться, как и ожидалось.

ActivityC - это новое действие, которого нет в задании, поэтому оно создано для вас.

Если в # 2 я покидаю приложение,Вместо кнопки homebutton все работает, как и ожидалось.

В прессе homebutton главное то, что в этом случае MainActivity не разрушается, а просто отодвигается на задний план.

Итак, после # 2ваш статус backstack будет выглядеть все еще с экземпляром MainActivity в качестве корня, например:

Main Activity (root)

Теперь, до # 5, backstack будет выглядеть следующим образом:

Main Activity (root) -> ActivityA -> ActivityB (top)

После # 5 ваш backstack выглядит так:

Main Activity (root) -> ActivityA -> ActivityB -> ActivityA (top)

Я полагаю, что причина этого в том, что MainActivity запускается по умолчанию с флагами намерений:

FLAG_ACTIVITY_NEW_TASK |FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

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

Более подробную информацию об этом можно найти здесь

И как я могу гарантировать, что действие всегда представлено?Я мог бы использовать FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP, но я хочу сохранить backstack.

Поскольку это структура данных стека , вы не можете изменить порядок своей деятельности, однако вы можете исправить это, добавивфлаг: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK в получателе, который создает ActivityA, поскольку это обеспечит создание нового экземпляра / задачи для действия независимо от того, присутствовало ли оно уже или нет.(Не рекомендуемое решение - но работает)

Но если вы хотите сохранить тот же экземпляр ActivityA, вам придется добавить параметр taskAffinity к вашей деятельности в манифесте.

<activity android:name=".ActivityB" android:taskAffinity="com.example.pendingintent"></activity>
<activity android:name=".ActivityA" android:taskAffinity="com.example.abctest" />

, а затем начните обе свои действия A и B с флагом new_task

Здесь - это отличное слайд-шоу, объясняющее taskAffinity и как оно влияет на создание действий.

0 голосов
/ 14 июня 2019

Вариант обновления 3: Это должно поднять активность на вершину.

intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

option1: установить FLAG_ACTIVITY_REORDER_TO_FRONT при запуске действия A. Это приведет к тому, что действие A окажется на вершине стека.

activityAIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

Опция 2: При просмотре документации Android только в «стандартном» режиме запуска создается несколько экземпляров действия.

См. Таблицу ниже.

Эта документация объясняет использование каждого режима: https://developer.android.com/guide/topics/manifest/activity-element.html#lmode

Добавьте стандартный launchMode в свой Activity A, если вы хотите каждый раз его новый экземпляр.

android:launchMode="standard"

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...