Java 从实例化活动的通知启动活动(即使已存在)

Java 从实例化活动的通知启动活动(即使已存在),java,android,android-notifications,android-pendingintent,activity-stack,Java,Android,Android Notifications,Android Pendingintent,Activity Stack,我的应用程序有一个后台服务,即使应用程序被销毁也可以运行。 该应用程序有两个活动:A,这是主要活动;B,一个设置活动。 每当应用程序进入后台时,就会创建通知。 如果我在A中,转到主屏幕并从通知中启动活动(意图为A),将创建一个新的(重复的)活动A 我想实现这个逻辑: if (launched from notification with app destroyed) { // this is the case where the service is running in backgro

我的应用程序有一个后台服务,即使应用程序被销毁也可以运行。
该应用程序有两个活动:A,这是主要活动;B,一个设置活动。
每当应用程序进入后台时,就会创建通知。
如果我在A中,转到主屏幕并从通知中启动活动(意图为A),将创建一个新的(重复的)活动A
我想实现这个逻辑:

if (launched from notification with app destroyed) {
    // this is the case where the service is running in background with the app destroyed
    create A;
} else {
    // don't create a new instance since A is already there. If current activity is B, stay in B (as if you pressed the launcher icon)
}
我目前使用以下PendingEvent从通知启动活动:

PendingIntent launchActivity = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
实现上述逻辑的正确方法是什么,最好是通过编程实现。谢谢

编辑:
标记活动\u SINGLE\u TOP
符合我的要求,但仍然存在一个问题:使用此标记,当且仅当活动位于堆栈顶部时,才会创建活动。 因此,在当前堆栈为[MainActivity>Settings]的情况下,由于设置位于堆栈顶部,因此新堆栈将为[MainActivity>Settings>MainActivity],但我想要的应该是[MainActivity>Settings]。

编辑2:基本上,单击通知应恢复应用程序的状态。

您可以打开重定向活动,而不是自己的活动:

public class RedirectAcivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, HomeActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
        finish();
    }
}
你的帐篷会像:

PendingIntent launchActivity = PendingIntent.getActivity(this, 0, new Intent(this, RedirectActivity.class), 0);

首先,尝试将
pendingent
标志设置为
pendingent.flag\u UPDATE\u CURRENT
而不是
0

PendingIntent launchActivity = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
然后为
活动
A(即
main活动
)设置
android:launchMode=“singleTop”
,以避免在打开时重新创建它:

<activity
    android:name=".MainActivity"
    ...
    android:launchMode="singleTop">
    ...
</activity>

谢谢,现在我编辑了PendingEvent并拥有
PendingEvent launchActivity=PendingEvent.getActivity(this,0,newintent(this,MainActivity.class)).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP),0)但唯一的问题是,当堆栈为[A,B]并且我转到主屏幕时,新堆栈将为[A]而不是[A,B]。我也试过只使用
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
,但结果是相同的,但是否可以使用Intent.FLAG_xxxs的适当组合获得我在问题中所说的内容(我编辑了更多细节)加上我在[注释]()中指定的内容
pendingent.FLAG\u UPDATE\u CURRENT
不会更改任何内容是否希望[MainActivity>Settings]堆栈并由MainActivity处理意图?正如您所知,暂停的活动无法处理意图,仍然处于暂停状态。我认为堆栈上只有两种选择:[MainActivity>Settings>MainActivity]和[MainActivity]“您想让[MainActivity>Settings]堆栈并由MainActivity处理意图吗?”是的!应该这样做。基本上,我想模仿发射器的行为。如果我有[MainActivity>Settings],进入主屏幕,从启动器启动应用程序,堆栈将是[MainActivity>Settings](我想要的!):我尝试了启动器标志:
FLAG\u ACTIVITY\u NEW\u TASK
FLAG\u ACTIVITY\u RESET\u TASK\u,如果需要的话
,但仍然不起作用:(您可能也看到了,这将导致您的root
活动的多个实例启动,即使它们不应该启动。为了确保您没有看到,请强制停止您的应用程序,然后点击主屏幕上的图标启动它,而不是从安装程序或IDE(Android Studio或其他)启动它)您好,谢谢您的回复。在搜索了一点之后,我确实找到了您链接的问题,现在我使用这个PendingEvent来完成我在实际问题中无法很好描述的事情:“在通知时恢复应用程序单击”:
Intent Intent=new Intent(Intent.ACTION\u MAIN).addCategory(Intent.CATEGORY\u LAUNCHER).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK _如果需要的话)。setComponent(新组件名(“com.example.app”,“com.example.app.MainActivity”);
。我唯一的问题是:这是完成我想做的事情的最干净的方法吗?看看一些Android,
NEW Intent(这个,FrameworkPerfActivity.class).setAction(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_启动器).addFlags(Intent.FLAG_活动_新任务),0)使用了
。我在我的应用程序中进行了尝试,该版本也可以使用……您建议使用哪一个版本?有很多方法可以做到这一点。它们都可以工作。您还可以使用`Intent Intent=getPackageManager().getLaunchIntentForPackage(“com.example.app”);'这代码稍微少一些,对读者来说可能更清晰。
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handleIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if(intent.hasExtra("KEY_TO_EXTRA")){
        // ...
    }
}