【问题标题】:Having One Instance Of Activity拥有一个活动实例
【发布时间】:2012-12-12 19:29:38
【问题描述】:

我在 Activity 导航和后台堆栈方面遇到问题,希望您能帮我解决。

问题

Root Activity >>> SecondActivity >> HomeButton

然后这会将我带到主页并从那里选择...

Gmail >> 消息 >> 在我的应用程序中打开附件 >> ImportActivity >> RootActivity

结果是启动了一个新任务,并使用了我的应用程序的另一个实例。这是不可接受的,因为我不想运行两个单独的任务,我只想要一个。

期望的结果

我想要发生的是当用户打开附件并且 ImportActivity 完成它的操作(它已将 android:noHistory 设置为 true)并调用 startActivity(intent)RootActivity 时启动,但在原始任务中只保留一个实例,其余的活动(在本例中为SecondActivity)被删除。

我想要这样做的原因是,如果用户在导入文件后导航出我的应用程序,然后触摸应用程序图标,它会加载第一个任务及其后堆栈,并且我有两个任务正在运行,用户可以在其中我的应用程序的不同部分。

我的尝试

我玩过启动模式,但它们都没有真正提供我需要的功能。

我尝试过的启动模式..

android:launchMode="singleTask" - 这只是在每次启动根活动时再次启动它。即使用户在我的应用程序中按下了主页按钮并触摸了应用程序图标,后台堆栈也会被破坏。

android:launchMode="singleInstance = 不允许任何其他活动在任务中运行。

另外,在调用意图启动RootActivity时,我使用了以下方法无济于事。

Intent i = new Intent(ImportActivity.this,TrackingActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);

有没有可能做我想做的事?

提前致谢

【问题讨论】:

  • 您是否尝试过使用单顶标志?
  • 在单任务模式下的 RootActivity 怎么样,你可以在 onPause() 中保存它的状态。当用户返回 RootActivity 时,会创建一个读取保存状态的新实例。
  • 在启动 TrackingActivity 时使用 Intent.FLAG_ACTIVITY_CLEAR_TASK
  • 你试过我关于taskAffinity的建议了吗?

标签: android android-intent android-activity android-lifecycle


【解决方案1】:

你说

Gmail >> Message >> Open attachment in my application >> ImportActivity >> RootActivity

但这可能不对。在这种情况下,gmail 会针对您应用中的ImportActivity 发出IntentImportActivity 将执行。但是,我对https://developer.android.com/guide/components/tasks-and-back-stack.html 的阅读表明,ImportActivity 将作为与 gmail 相同任务的一部分执行,并将被放在 gmail 任务的后台堆栈顶部,除非您在清单中采取特殊步骤来防止这种情况发生或gmail 专门将其作为单独的任务调用。当ImportActivity 完成时,它不应该调用startActivity(intentForRootActivity),而应该只调用finish(),这样它就会被销毁,并且位于它下面的位于后堆栈中的来自gmail 的活动将会出现。

如果ImportActivity 确实调用了startActivity(intentForRootActivity),那么RootActivity 只会进入gmail 任务的顶部并出现在gmail 后台堆栈中。触摸home,然后gmail的启动器图标会看到RootActivity重新出现,将gmail隐藏在下面。

我认为您在 ImportActivity 的清单声明中需要 android:launchMode="standard"

不会修改代表您应用的较旧的独立实例的任务。如果有人触摸了您应用的启动器图标,您的应用的旧状态将被恢复,不受 gmail 任务中发生的任何事情的影响。

http://developer.android.com/guide/components/processes-and-threads.html 文档对于活动如何映射到此处的进程相当含糊(导致 David Wasser 评论我的早期版本的这个答案),但似乎 gmail 的活动将在一个 linux 进程中与一个 linux 用户一起执行id 和 ImportActivity 将在另一个具有另一个用户 ID 的 linux 进程中执行。但是,它们都可以构成具有一个回栈的一项任务的一部分。

ImportActivity 将作为 gmail 任务的一部分执行,其有效 Linux 用户 ID 与它作为独立应用程序的一部分执行时相同 - 与 gmail 执行时使用的 Linux 用户 ID 不同。这听起来不太可能而且很复杂,但https://developer.android.com/guide/components/fundamentals.html 似乎暗示了这一点。这就说得通了;如果ImportActivity 需要获取为您的应用存储的用户首选项,它需要读取首选项文件,就好像它是为您的应用定义的用户,而不是为 gmail 定义的用户。

我还没有尝试执行任何这些。如果我完全掌握了错误的一端,我相信很快就会有人告诉我们!

【讨论】:

  • 您在此答案开头的陈述是错误的。您混淆了 2 个完全不同的概念:Android task 不是操作系统 process。 Android 的安全模型为每个应用程序使用唯一的用户 ID,并依赖于操作系统的安全机制。这意味着您的代码将从不与 Gmail 代码在相同的进程(内存)空间中运行,并且它从不与 Gmail(或任何其他应用程序)具有相同的用户 ID )。导入活动可能与他的 Gmail 应用程序在同一个任务堆栈中,这取决于 Gmail 如何启动活动。
  • 是的,我同意你的观点,任务不是进程,用户 ID 是特定于应用程序的,import 的任务堆栈可以取决于 gmail 如何发送意图.您能否指导我查看解释活动如何映射到流程的文档?我没找到。
  • developer.android.com/guide/components/… 第一段声明应用程序的组件(Activity、Service、BroadcastReceiver、ContentProvider)都在同一个进程中一起运行(默认情况下)。如果需要,您可以在清单中指定哪些组件在哪个进程中运行。安全模型的详细描述(也解释了很多关于组件、流程等)可以在这里找到:source.android.com/tech/security/index.html
  • 是的,谢谢,我在你打字的时候找到了答案并重写了答案。默认情况下,应用程序的组件都在同一个进程中运行 - 但是作为另一个应用程序的一部分的 Activity 会发生什么情况呢?这不是明确的。但是,我同意您的解释似乎比我原来的解释更有可能。感谢您的指正。
  • 第一句是“当一个应用程序组件启动并且该应用程序没有任何其他组件在运行时,Android系统为该应用程序启动一个新的Linux进程,单线程执行。”所以这很清楚。如果我启动了您的一项活动并且您的应用未运行,则会创建一个新进程来托管您的活动。
【解决方案2】:

您不需要任何特殊的launchMode 来执行此操作。如果您的导入活动使用Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP 启动根活动,这应该可以满足您的需求。我猜你对taskAffinity 有疑问。试试这个:

在您的清单中,在 importActivity 的声明中添加:

android:taskAffinity=""

如果这不起作用,请发布您的清单以便我们查看。

【讨论】:

    【解决方案3】:

    我真的不确定我是否得到它,但如果你想在不丢失额外应用程序堆栈的情况下进入你的“根”活动,它将是 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP 直接在你的 intent 的标志上,并且没有Manifest...

    【讨论】:

    • 对不起,如果我不清楚,我认为你没有在这里回答。如果调用 ImportActivity,我想丢失我之前的堆栈。从那里我导航到上一个任务的RootActivity。我不想要两个单独的任务
    • android:launchMode="singleTask" 在 ImportActivity 的 mainfest。 “系统在新任务的根部创建活动并将意图路由到它。但是,如果活动的实例已经存在,系统将通过调用其 onNewIntent() 方法将意图路由到现有实例,而不是而不是创建一个新的。”
    • 我想成为根的活动是RootActivity。我已经尝试过singleTask,但是它似乎总是创建一个新任务而不是(就像你引用的那样)“系统将意图路由到现有实例”
    • 您是否尝试过在您的 AndroidManifest.xml 上使用 android:launchMode="singleInstance" ?
    • 是的,问题在于,这个活动将独自完成一项任务......
    猜你喜欢
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    相关资源
    最近更新 更多