Ярлык приложения работает только один раз, после этого приложение возобновляется.

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

ShortcutInfo composeShortcut = new ShortcutInfo.Builder(App.getInstance(),
                                                                           getString(R.string.compose_shortcut_id))
                    .setShortLabel(getString(R.string.compose_app_shortcut_short_label))
                    .setLongLabel(getString(R.string.compose_app_shortcut_long_label))
                    .setDisabledMessage(getString(R.string.compose_app_shortcut_disabled_message))
                    .setIcon(Icon.createWithResource(App.getInstance(), R.drawable.compose_icon))
                    .setIntent(new Intent(context, ComposeActivity.class))
                                              .setAction(Intent.ACTION_DEFAULT)
                                              .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP))
                    .build();
            shortcutManager.setDynamicShortcuts(Arrays.asList(composeShortcut));

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

Требуемый поток - при каждом нажатии ярлыка приложения должна открываться функция ComposeActivity. Если приложение уже запущено, ComposeActivity должно открываться поверх текущего действия, только если текущее действие еще не является ComposeActivity.

Текущий поток - при первом нажатии на ярлык приложения активность "Создать" открывается просто отлично, но не после этого. Приложение возобновляется только после этого. Я должен убить приложение и снова нажать на ярлык, чтобы открыть ComposeActivity.

Больше информации - Составить Активность в AndroidManifest определяется следующим образом:

...
<activity 
android:name=".shared.publish.compose.view.activity.ComposeActivity"
android:screenOrientation="portrait"
android:theme="@style/compose_theme"
android:windowSoftInputMode="stateVisible|adjustResize"/>

<activity
    android:name=".shared.activity.SplashScreenActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait"
    android:theme="@style/splash_screen_theme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>
...

2 ответа

Решение

Вот и я наконец нашел решение. Благодаря некоторой полезной информации от Дэвида Вассера.

Во-первых, ярлык приложения работает для действий с действием MAIN и категория LAUNCHER,

Таким образом, в манифесте я добавил следующий фильтр намерений для моей ComposeActivity

 <Activity android:name=".view.activity.ComposeActivity"
     android:relinquishTaskIdentity="true">
     <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
     </intent-filter> 
 </Activity>

Если вы посмотрите внимательно, я также установил android:relinquishTaskIdentity="true", Это гарантирует, что если я уже открыл ComposeActivity из ярлыка, а затем я могу снова использовать его и открыть ComposeActivity.

Затем я обновил Intent, используемый для ярлыка

new Intent(context, ComposeActivity.class))
.setAction(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)

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

Но есть одна проблема. Если нет открытых действий, то Compose не будет иметь никаких действий ниже этого. Приложение закроется, если нажать кнопку назад.

Одна вещь, которую вы можете сделать, это

@Override
public void onBackPressed() {
    if(isTaskRoot()){
        if (getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) 
              && Intent.ACTION_MAIN.equals(getIntent().getAction())) {
            //launch any activity
        }
    }
    finish();
}

С этим я мог открыть любую активность, когда ComposeActivity является единственной активностью в заднем стеке. В моем случае я запустил HomeActivity.

Как я и ожидал, проблема связана с использованием вами ShortcutManager, Вот важный бит из документации:

Только основные действия - действия, которые управляют действием MAIN и категорией LAUNCHER - могут иметь ярлыки. Если приложение имеет несколько основных действий, эти действия имеют разные наборы ярлыков.

Что происходит, что ваш ярлык Intent выглядит как пусковая установка Intent, Когда пользователь нажимает на значок приложения, это создает панель запуска Intent (ДЕЙСТВИЕ = ГЛАВНАЯ и КАТЕГОРИЯ = ЗАПУСК). Затем Android проверяет, есть ли уже активная задача с этим средством запуска Activity как корень Activity, Если он находит его, все, что он делает, - выводит эту задачу на передний план. Если он не находит, он создает новую задачу и запускает программу запуска Activity в новую задачу в качестве корня Activity, Это именно то поведение, которое вы видите, и именно то, что ожидают пользователи. Если вы используете Gmail или какое-либо другое приложение, а затем принимаете вызов (переводя это приложение в фоновый режим), то когда вы вернетесь к экрану HOME и снова щелкните значок этого приложения, вы ожидаете, что вы вернетесь в приложение именно как ты это оставил. Это стандартное и ожидаемое поведение Android.

Пожалуйста, прочтите также раздел в документации под названием "Ярлыки ярлыков", в который входит этот драгоценный камень:

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

Вам нужно переосмыслить свою навигацию, чтобы она имела смысл для пользователей (и она следует стандартным шаблонам Android).

Другие вопросы по тегам