返回

安卓应用程序如何进行技术重启?

Android

## 从技术角度重新启动安卓应用程序

### 简介

安卓系统通常不建议强行终止或重启应用程序。然而,在某些特定的情况下,可能需要执行此操作。本文将探讨如何通过编程方式重新启动安卓应用程序,解决特定使用场景中的问题。

### 问题

在一个特定的使用场景中,应用程序需要在收到来自服务器的特定信息时执行恢复出厂设置。由于用户只能使用一个应用程序实例在服务器上登录,因此如果出现另一个实例获取“已登录”锁定的情况,则该用户的所有其他实例必须删除其数据(恢复出厂设置),以保持一致性。

为了防止用户通过删除和重新安装应用程序来强制获取锁定,应用程序需要不断检查其是否拥有锁定。这个检查几乎在每次向服务器发送请求时都会进行。如果服务器发送“错误锁定 ID”,则客户端应用程序必须删除所有数据。

### 解决方法

在这个使用场景中,应用程序包含多个活动和服务:

  • 活动 A: 启动登录活动或应用程序的主活动
  • 活动 B: 应用程序的主活动
  • 活动 C: 由 B 启动的活动
  • 意图服务 D: 由 C 通过 startService 启动

当意图服务 D 的 onHandleIntent 方法处理一个事件时,它会将该事件发送到结果接收器 R。R 处理事件并向用户提供一个对话框,用户可以在其中选择恢复应用程序的出厂设置(删除数据库、清除共享首选项等)。

恢复出厂设置后,我们需要重新启动应用程序(关闭所有活动),并仅重新启动活动 A,然后启动登录活动 L 并结束自身:

(A) > L

使用 FLAG_ACTIVITY_NEW_TASK 时,活动 B 和 C 仍然运行。如果在登录活动中按下返回按钮,则会看到 C,但我们希望返回到主屏幕。

如果不设置 FLAG_ACTIVITY_NEW_TASK,则会收到以下错误:

07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

由于服务意图 D 也可能由警报管理器启动的后台任务调用,因此我们无法使用活动的上下文。

为了解决此问题并使活动堆栈变为 (A) > L,我们需要:

  1. 使用 FLAG_ACTIVITY_CLEAR_TOP 来关闭活动堆栈中的所有活动。
  2. 使用 FLAG_ACTIVITY_CLEAR_TASK 来关闭整个任务(应用程序实例)。
  3. 添加 android:launchMode="singleTop" 属性到登录活动 L 的清单文件中。

### 代码实现

更新后的代码如下所示:

@Override
public void onClick(DialogInterface dialog, int which) {

    // 将调用 onCancelListener
    MyApplication.factoryReset(); // (删除数据库、清除共享首选项等)
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);
}

清单文件中登录活动 L 的配置:

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

通过这些修改,我们确保在恢复出厂设置后关闭所有活动和任务,并仅启动登录活动 L。活动 L 由于其 android:launchMode="singleTop" 属性,将成为活动堆栈的根活动。

### 常见问题解答

  1. 为什么要使用 FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_CLEAR_TASK
    • FLAG_ACTIVITY_CLEAR_TOP 会关闭活动堆栈中的所有活动。
    • FLAG_ACTIVITY_CLEAR_TASK 会关闭整个任务(应用程序实例)。
  2. 为什么要使用 FLAG_ACTIVITY_NEW_TASK
    • FLAG_ACTIVITY_NEW_TASK 会创建一个新的任务(应用程序实例),并启动指定的活动作为该任务的根活动。
  3. 为什么要设置 android:launchMode="singleTop"
    • android:launchMode="singleTop" 指定当该活动已经处于活动堆栈的顶部时,启动该活动的行为。在这种情况下,活动将保持不变,并且不会创建新的活动实例。
  4. 如果应用程序在后台运行,如何重新启动它?
    • 您可以使用 IntentFLAG_ACTIVITY_NEW_TASK 来从后台重新启动应用程序。
  5. 如何关闭所有应用程序活动?
    • 您可以使用 finishAffinity 方法来关闭应用程序的所有活动。