【问题标题】:Show dialog activity over another app from background从后台显示另一个应用程序的对话框活动
【发布时间】:2017-01-21 14:44:59
【问题描述】:

假设您有一个应用程序 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);

来自应用 A(后台应用)。

但是,当我这样做时,对话框会插入到 原始应用程序 A 活动和后端堆栈上的应用程序 B 活动之间。

【问题讨论】:

    标签: android android-activity android-dialog android-task


    【解决方案1】:

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

    • 对话框活动必须具有半透明主题,以允许其他应用程序显示在其后面(请参阅@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);
    

    在上面,baseActivity 是对应用程序主要活动的引用。

    给对话活动一个launchModesingleInstance 可能会有所帮助,确保它永远不会在其任务中累积其他活动,但这可能是不必要的。 @android:style/Theme.Translucent.NoTitleBar 主题允许其下方的活动显示出来。

    <activity
        android:name=".DialogActivity"
        android:launchMode="singleInstance"
        android:theme="@android:style/Theme.Translucent.NoTitleBar">
    </activity>
    

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

     getWindow().setLayout(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    );
    

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

    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    

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

    class DialogActivity extends Dialog { ... }
    

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

    【讨论】:

    • 如果您尝试此操作并在后台现有活动之上获取新对话框,请尝试在清单中添加 android:taskAffinity="",以便您的透明活动始终在新任务中打开正如这个答案stackoverflow.com/questions/35728917/…中所阐明的那样
    【解决方案2】:

    我认为 Nanda Gopal 在另一个线程中回答了这个问题。但不是在这里,所以让我试试。

    我的解决方案来自:https://blog.mindorks.com/how-to-create-a-transparent-activity-in-android

    这是:

     <style name="Theme.AppCompat.Transparent.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
    </style>
    

    但是由于我在没有 Compat 或 Support 库的手机上使用 APK Builder;以下对我有用:

     <style name="Test" parent="@android:style/Theme.Dialog">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
    </style>
    

    【讨论】:

      【解决方案3】:

      是的,这是可能的。您需要实现自定义操作和广播接收器以注册您的自定义事件。

      您的应用 A 触发了一个自定义操作,而您在应用 B 中编写并注册到该操作的广播接收器可以检测到事件。然后你需要在你的接收器中显示对话框。

      这可能很棘手。祝你好运

      【讨论】:

      • 我只是稍微澄清一下我的帖子 - 这种情况下的应用程序 B 不是我正在编写的应用程序。它实际上是设备上预先存在的应用程序。
      • 所以如果问题是如何显示对话框,你已经给出了正确的答案。您需要像 Facebook Messenger 那样使用浮动视图。您可以通过将浮动头写为信使关键字在网络上找到教程
      • 有没有办法通过在应用 B 前面显示来自应用 A(理想情况下非全屏)的活动来做到这一点?而不是像 Facebook 那样采用浮动视图使用窗口管理器的方法?基本上,我可以简单地将一个应用程序 A 的活动放在应用程序 B 的活动前面,这将是最简单的方法。但我不确定这是否可能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 2019-01-30
      • 1970-01-01
      相关资源
      最近更新 更多