0

我有一个看起来像这样的动态应用快捷方式

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 都应该打开。如果应用程序已经在运行,那么仅当当前 Activity 还不是 ComposeActivity 时,ComposeActivity 才应该在当前 Activity 之上打开。

当前流程- 我第一次按下应用程序快捷方式时,Compose 活动打开得很好,但在那之后就不行了。应用程序仅在此之后恢复。我必须终止该应用程序并再次单击它的快捷方式以打开 ComposeActivity。

更多信息 - AndroidManifest 中的 Compose Activity 定义如下:

...
<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>
...
4

2 回答 2

1

正如我所料,问题是由于您使用ShortcutManager. 这是文档中的重要部分:

只有主要活动——处理 MAIN 动作和 LAUNCHER 类别的活动——可以有快捷方式。如果一个应用程序有多个主要活动,这些活动有不同的快捷方式集。

发生的情况是您的快捷方式Intent看起来像一个启动器Intent。当用户单击应用程序图标时,会生成一个启动器Intent(ACTION=MAIN 和 CATEGORY=LAUNCHER)。然后,Android 会查看是否已经有一个以这个启动器Activity为根的活动任务Activity。如果它找到了,它所做的就是将这项任务带到前台。如果找不到,它会创建一个新任务并将启动器Activity作为根启动到新任务中Activity. 这正是您所看到的行为,也正是用户所期望的。如果您正在使用 Gmail 或其他应用程序,然后接听电话(将该应用程序推到后台),那么当您返回主屏幕并再次单击该应用程序图标时,您希望返回到应用程序你离开它的方式。这是标准和预期的 Android 行为。

另请阅读文档中标题为“Shortcut Intents”的部分,其中包括此 gem:

可以使用任何一组 Intent 标志发布动态快捷方式。通常,指定 FLAG_ACTIVITY_CLEAR_TASK,可能与其他标志一起指定;否则,如果应用程序已经在运行,应用程序只是被带到前台,并且目标活动可能不会出现。

您需要重新考虑您的导航,以便它对用户有意义(并且它遵循标准的 Android 模式)。

于 2017-07-21T16:40:12.493 回答
0

所以我终于找到了解决方案。感谢 David Wasser 提供的一些有用信息。

首先,App 快捷方式适用于带有 ActionMAIN和 Category的 Activity 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。

于 2017-07-23T14:01:57.890 回答