在后台显示另一个应用程序的对话框活动

Chr*_*ton 5 android android-dialog android-activity android-task

假设您有一个应用程序A,它可以打开另一个不受您控制的应用程序B(例如,地图)(即它是一个已有的应用程序)。因此,现在应用程序A在后台。假设发生了一个事件,并且A希望在应用B的UI上显示一个浮动对话框(同时使应用B的活动保持可见)。这可能吗?

(对此的通常答案是显示通知,但这不是大众市场应用,我们正在尝试直接吸引用户的注意。)

目前,我正在尝试执行以下操作:

// This code runs in a class other than app A's main activity,
// and the "activity" variable used here is a reference to that activity.
Intent intent = new Intent(activity, NotificationDialogActivity.class);
// EDIT: I'm not exactly sure whether NEW_TASK helps here or not
// so I removed it, but the REORDER_TO_FRONT would ideally cause
// app A's dialog activity to be moved to the front of the back stack?
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
// The "msg" variable here is just some data being passed to the dialog activity
// I included it here only so it is clear that there is a purpose.
intent.putExtra(NotificationDialogActivity.EXTRA_MSG, msg);
activity.startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

从应用程序A(背景中的一个)中获取。

但是,当我执行此操作时,将发生对话框被插入原始应用程序A活动和后台堆栈中的应用程序B活动之间的情况。

Chr*_*ton 8

为了使对话框活动显示在另一个应用程序上,必须做一些事情:

  • 对话框活动必须具有半透明的主题,以允许其他应用程序显示在其后面(请参阅参考资料@android:style/Theme.Translucent.NoTitleBar)。
  • 出于相同的原因,对话框活动不能填满屏幕(请参阅参考资料Window.setLayout
  • 对话框活动必须是与基本活动分开的任务的一部分,这样,当对话框活动显示在另一个应用程序上方时,它也不会将基础活动也拉到另一个应用程序上方(请参阅参考资料FLAG_ACTIVITY_NEW_TASK)。
  • 必须将对话框活动置于最前面,以便从中启动该活动的活动在后台运行(请参阅参考资料FLAG_ACTIVITY_REORDER_TO_FRONT)。
  • 对话框活动必须以某种方式显示对话框,例如,通过创建Dialog直接扩展该类的类

在启动对话框活动的代码中:

Intent intent = new Intent(baseActivity, DialogActivity.class);
// NEW_TASK allows the new dialog activity to be separate from the existing activity.
// REORDER_TO_FRONT causes the dialog activity to be moved to the front,
// if it's already running.
// Without the NEW_TASK flag, the existing "base" activity
// would be moved to the front as well.
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(DialogActivity.EXTRA_SOME_PARAM, someParamValue);
// The activity must be started from the application context.
// I'm not sure why exactly.
baseActivity.getApplicationContext().startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

以上baseActivity是对应用程序主要活动的引用。

为对话框活动设置a可能会有所帮助,确保对话框活动launchModesingleInstance从不积累其他活动,但这可能是不必要的。该@android:style/Theme.Translucent.NoTitleBar主题允许的活动下它显示出来。

<activity
    android:name=".DialogActivity"
    android:launchMode="singleInstance"
    android:theme="@android:style/Theme.Translucent.NoTitleBar">
</activity>
Run Code Online (Sandbox Code Playgroud)

对于对话框活动本身,可能有必要调整其窗口以确保它不会填满整个屏幕:

 getWindow().setLayout(
    ViewGroup.LayoutParams.MATCH_PARENT,
    ViewGroup.LayoutParams.WRAP_CONTENT
);
Run Code Online (Sandbox Code Playgroud)

同样,在对话框活动的布局XML中,也可能有必要:

android:layout_width="fill_parent"
android:layout_height="wrap_content"
Run Code Online (Sandbox Code Playgroud)

对于对话框本身,您可以做很多事情,但是一种解决方案是扩展Dialog类:

class DialogActivity extends Dialog { ... }
Run Code Online (Sandbox Code Playgroud)

要显示活动中的对话框,只需创建Dialog的新实例并调用其show()方法。

  • 如果您尝试此操作并在后台现有活动之上获取新对话框,请尝试在清单中添加 android:taskAffinity="" ,以便您的透明活动始终在新任务中打开,如本答案 https:// 中所述/stackoverflow.com/questions/35728917/notification-intent-opens-the-apps-main-activity-in-background-if-its-paused?rq=1 (2认同)