Android 平台指南

本指南将帮助您设置开发环境,以便在 Android 设备上构建 Cordova 应用程序。此外,它还提供了将 Android 特定的命令行工具集成到您的开发工作流程中的选项。

无论您打算使用 Android 特定的命令行工具还是 Cordova CLI 命令,您都需要安装和配置必要的组件。

Android API 级别支持

下表列出了与 Cordova-Android 发布版本相对应的支持的 Android API 级别(Android 版本)。

cordova-android 版本 Android API 级别(Android 版本) 库和工具版本
12.0.x 24 (7.0) - 33 (13.0)
  • 构建工具:^33.0.2
  • Kotlin:1.7.21
  • Gradle:7.6
  • Android Gradle 插件:7.4.2
  • AndroidX Compat 库:1.6.1
  • AndroidX WebKit 库:1.6.0
  • AndroidX Core SplashScreen:1.0.0
  • Google Services Gradle 插件:4.3.15
11.0.x 22 (5.1) - 32 (12L)
  • 构建工具:^32.0.0
  • Kotlin:1.7.21
  • Gradle:7.4.2
  • Android Gradle 插件:7.2.1
  • AndroidX Compat 库:1.4.2
  • AndroidX WebKit 库:1.4.0
  • AndroidX Core SplashScreen:1.0.0-rc01
  • Google Services Gradle 插件:4.3.10
10.1.x 22 (5.1) - 30 (11.0)
  • 构建工具:^30.0.3
  • Kotlin:1.5.21
  • Gradle:7.1.1
  • Android Gradle 插件:4.2.2
  • AndroidX Compat 库:1.3.1
  • AndroidX WebKit 库:1.4.0
  • Google Services Gradle 插件:4.3.8
10.0.x 22 (5.1) - 30 (11.0)
  • 构建工具:^30.0.3
  • Kotlin:1.5.20
  • Gradle:7.1.1
  • Android Gradle 插件:4.2.2
  • AndroidX Compat 库:1.3.0
  • AndroidX WebKit 库:1.4.0
  • Google Services Gradle 插件:4.3.5
9.X.X 22 (5.1) - 29 (10.0) -
8.X.X 19 (4.4) - 28 (9.0) -
7.X.X 19 (4.4) - 27 (8.1) -
6.X.X 16 (4.1) - 26 (8.0) -
5.X.X 14 (4.0) - 23 (6.0) -
4.1.X 14 (4.0) - 22 (5.1) -
4.0.X 10 (2.3.3) - 22 (5.1) -
3.7.X 10 (2.3.3) - 21 (5.0) -

注意:上面列出的 cordova-android 版本不是 Cordova CLI 版本。

要找出 Cordova 项目中安装的 Cordova-Android 包的版本,请导航到项目的根目录并执行命令 cordova platform ls

Cordova 通常会停止对 Google 分发仪表板中低于 5% 的 Android 版本的支持。您可以参考 Google 的 分发仪表板 获取更多信息。

系统要求

Cordova-Android 依赖于 Android SDK,Android SDK 可以安装在 macOS、Linux 或 Windows 操作系统上。

要确保您的系统满足必要的要求,请参考 Google 提供的“安装 Android Studio”指南。

所需软件和工具

Java 开发工具包 (JDK)

如果您使用的是 cordova-android 10.0.0 或更高版本,请安装 Java 开发工具包 (JDK) 11

如果您使用的是 cordova-android 10.0.0 以下的任何版本,请安装 Java 开发工具包 (JDK) 8

必须根据您的 JDK 安装路径设置 JAVA_HOME 环境变量。请参阅 设置环境变量 部分了解如何设置环境变量。或者,从 cordova-android 10.0.0 或更高版本开始,可以设置 CORDOVA_JAVA_HOME 来代替 JAVA_HOME,允许专门用于 Cordova 开发的 JDK 安装。

Gradle

从 Cordova-Android 6.4.0 开始,需要安装 Gradle

在 Windows 上安装时,您需要将 Gradle 二进制目录的路径添加到您的 path 环境变量中。请参阅 设置环境变量)了解如何配置系统环境变量。

注意:这是系统的 Gradle 版本。系统的 Gradle 二进制文件将创建 Gradle Wrapper 文件,该文件声明并获取构建 Android 应用程序所需的适当 Gradle 版本。系统级和项目级 Gradle 版本可能不匹配,也不需要匹配。项目级的 Gradle 版本在 Cordova-Android 的包中定义,并根据 Android 支持的内容进行设置。

Android Studio

下载并安装 Android Studio。按照链接的 Android 开发者网站上的说明开始使用。

第一次打开 Android Studio 将引导您完成安装 Android SDK 包的过程。

SDK 包

建议根据项目中安装的 Cordova-Android 版本安装最新版本的 SDK 平台和 SDK 工具。请参阅 Android API 级别支持 部分,了解根据 Cordova-Android 版本支持的版本。

安装 SDK 平台
  1. 打开 Android Studio 的
  2. 打开 SDK 管理器工具 > SDK 管理器
  3. 单击 SDK 平台选项卡
  4. 选择与 Android API 级别支持 中支持的最高 SDK 相匹配的 Android 版本
  5. 单击应用

例如:如果项目已安装 [email protected],则支持的最高 SDK 为 33。在上面的步骤 3 中,应选择“Android 13.0 (Tiramisu)”。

Android SDK Platform

安装 Android SDK 构建工具
  1. 打开 Android Studio 的
  2. 打开 SDK 管理器工具 > SDK 管理器
  3. 单击 SDK 工具选项卡
  4. 选中 显示包详细信息
  5. 展开 Android SDK 构建工具
  6. 根据 Android API 级别支持 选中支持的最高构建工具。
  7. 单击应用

例如:如果项目已安装 [email protected],则支持的最高 SDK 为 33。我们希望选择 33.x 的最高可用版本。在撰写本文时,应在步骤 6 中选择“33.0.2”。

Android SDK Build-Tools

安装 Android SDK 命令行工具(最新)
  1. 打开 Android Studio 的
  2. 打开 SDK 管理器工具 > SDK 管理器
  3. 单击 SDK 工具选项卡
  4. 选中 显示包详细信息
  5. 展开 Android SDK 命令行工具(最新)
  6. 选中 Android SDK 命令行工具(最新)
  7. 单击应用

SDK Command-line Tools (latest)

安装 Android SDK 平台工具
  1. 打开 Android Studio 的
  2. 打开 SDK 管理器工具 > SDK 管理器
  3. 单击 SDK 工具选项卡
  4. 选中 显示包详细信息
  5. 选中 Android SDK 平台工具
  6. 单击应用

Android SDK Platform-Tools

安装 Android 模拟器
  1. 打开 Android Studio 的
  2. 打开 SDK 管理器工具 > SDK 管理器
  3. 单击 SDK 工具选项卡
  4. 选中 显示包详细信息
  5. 选中 Android 模拟器
  6. 单击应用

Android Emulator

设置环境变量

Cordova 的 CLI 需要特定的环境变量才能正常运行。如果缺少环境变量,CLI 将尝试临时解析该变量。如果缺少的变量无法解析,则必须手动设置。

必须设置以下变量

  • JAVA_HOME - 指向 JDK 安装位置的环境变量
  • ANDROID_HOME - 指向 Android SDK 安装位置的环境变量

还建议更新 PATH 环境变量以包含以下目录。

  • cmdline-tools/latest/bin
  • platform-tools
  • build-tools
  • emulator
    • 这是 apksignerzipalign 工具所必需的。

注意:上面的目录通常位于 Android SDK ROOT 中。

macOS 和 Linux

在 Mac 或 Linux 上,使用文本编辑器创建或修改 ~/.bash_profile 文件。

要设置环境变量,请添加一行使用 export 的代码,如下所示(将路径替换为您的本地安装路径)

export ANDROID_HOME=/Development/android-sdk/

要更新您的 PATH,请添加类似以下内容的一行(将路径替换为您的本地 Android SDK 安装位置)

export PATH=$PATH:$ANDROID_HOME/platform-tools/
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin/
export PATH=$PATH:$ANDROID_HOME/build-tools
export PATH=$PATH:$ANDROID_HOME/emulator/

重新加载您的终端以查看此更改的反映,或运行以下命令

source ~/.bash_profile

Windows

这些步骤可能因您安装的 Windows 版本而异。在进行更改后关闭并重新打开任何命令提示符窗口以查看更改的反映。

  1. 单击 开始菜单或按 Windows 键 (Win)
  2. 在搜索栏中键入 环境变量
  3. 选择 编辑系统环境变量选项
  4. 在出现的窗口中单击 环境变量… 按钮。
要创建新的环境变量
  1. 单击 新建… 按钮
  2. 键入 变量名
  3. 键入 变量值
  4. 单击 确定按钮
要设置您的 PATH
  1. 从已定义变量列表中选择 PATH
  2. 单击 编辑… 按钮
  3. 单击 新建按钮
  4. 键入相关位置。

重复步骤 3 和 4,直到添加所有路径。

示例路径(将路径替换为您的本地 Android SDK 安装位置)

C:\Users\[your user]\AppData\Local\Android\Sdk\platform-tools
C:\Users\[your user]\AppData\Local\Android\Sdk\cmdline-tools\latest\bin
C:\Users\[your user]\AppData\Local\Android\Sdk\build-tools
C:\Users\[your user]\AppData\Local\Android\Sdk\emulator

添加所有路径后,单击 确定按钮,直到关闭所有用于设置和编辑环境变量的打开窗口。

项目配置

设置模拟器

如果您希望在 Android 模拟器上运行 Cordova 应用程序,则首先需要创建一个 Android 虚拟设备 (AVD)。

有关以下 Android 文档的更多详细信息,请参阅

配置好 AVD 后,您应该能够通过运行以下命令将 Cordova 应用程序部署到模拟器

cordova run --emulator

配置 Gradle

Cordova-Android 项目使用 Gradle 构建。

设置 Gradle 属性

可以通过设置 Cordova 公开的某些 Gradle 属性 的值来配置 Gradle 构建。

以下属性可用

属性 描述
cdvAndroidXAppCompatVersion 设置 androidx.appcompat:appcompat 库的版本。
cdvAndroidXWebKitVersion 设置 androidx.webkit:webkit 库的版本。
cdvBuildArch 覆盖构建应用程序的构建体系结构。默认值由 Cordova 的构建脚本自动检测。
cdvBuildMultipleApks 如果设置了此选项,则将生成多个 APK 文件:每个库项目支持的原生平台一个(x86、ARM 等)。如果您的项目使用大型原生库,这可能很重要,因为这会大大增加生成的 APK 的大小。如果未设置,则将生成一个可以在所有设备上使用的 APK
cdvBuildToolsVersion 覆盖自动检测的 android.buildToolsVersion
cdvCompileSdkVersion 设置应用程序编译的框架的 SDK 版本。设置将覆盖 android.compileSdkVersion 值的自动检测。
cdvDebugSigningPropertiesFile 默认:debug-signing.properties
指向包含调试构建签名信息的 .properties 文件的路径(请参阅 签名应用程序)。当您需要与其他开发人员共享签名密钥时,这很有用
cdvMaxSdkVersion 设置应用程序可以运行的最高 API 级别
cdvMinSdkVersion 覆盖在 AndroidManifest.xml 中设置的 minSdkVersion 值。在根据 SDK 版本创建多个 APK 时很有用。
cdvReleaseSigningPropertiesFile 默认值:release-signing.properties
指向包含发布版本签名信息的 .properties 文件的路径(请参阅 签名应用程序)。
cdvSdkVersion 覆盖 targetSdkVersion 值。
cdvVersionCode 覆盖在 AndroidManifest.xml 中设置的 versionCode。
cdvVersionCodeForceAbiDigit 是否在仅构建单个 APK 时将 0 “abi 数字” 附加到 versionCode。

您可以通过以下四种方式之一设置这些属性

  • 使用环境变量

    示例

      export ORG_GRADLE_PROJECT_cdvMinSdkVersion=20
      cordova build android
    
  • 使用 Cordova buildrun 命令的 --gradleArg 标志

    示例

      cordova run android -- --gradleArg=-PcdvMinSdkVersion=20
    
  • 在项目的 Android 平台目录中创建 gradle.properties

    在目录 <project-root>/platforms/android 中创建一个名为 gradle.properties 的文件,其内容如下所示

    示例文件内容

      cdvMinSdkVersion=20
    
  • 扩展 build.gradle 与 `build-extras.gradle 文件

    在目录 <project-root>/platforms/android/app 中创建一个名为 build-extras.gradle 的文件,其内容如下所示

      ext.cdvMinSdkVersion = 20
    

后两种选项都涉及在您的 Android 平台文件夹中包含一个额外的文件。通常,不建议编辑此文件夹的内容,因为这些更改很容易丢失或被覆盖。相反,这些文件应该作为构建命令的一部分使用 before_build 钩子脚本 复制到该文件夹中。

扩展 build.gradle

如果您需要自定义 build.gradle 文件,而不是直接编辑它,建议创建一个名为 build-extras.gradle 的同级文件。如果存在,此文件将被主 build.gradle 脚本包含。此文件必须放在 Android 平台目录的 app 文件夹中(<your-project>/platforms/android/app)。建议使用 before_build 钩子脚本 将此文件复制过来。

以下是一个示例

// Example build-extras.gradle
// This file is included at the beginning of `build.gradle`

// special properties (see `build.gradle`) can be set and overwrite the defaults
ext.cdvDebugSigningPropertiesFile = '../../android-debug-keys.properties'

// normal `build.gradle` configuration can happen
android {
  defaultConfig {
    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
  }
}
dependencies {
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
  }
}

// When set, this function `ext.postBuildExtras` allows code to run at the end of `build.gradle`
ext.postBuildExtras = {
    android.buildTypes.debug.applicationIdSuffix = '.debug'
}

请注意,插件也可以通过以下方式包含 build-extras.gradle 文件

<framework src="some.gradle" custom="true" type="gradleReference" />

配置 Gradle JVM 参数

要更改 Gradle JVM 参数,可以使用 --jvmargs 标志与 Cordova 的 buildrun 命令一起使用。这主要用于控制 Gradle 在构建过程中允许使用的内存量。建议至少允许 2048 MB。

默认情况下,JVM 参数的值为 -Xmx2048m。要增加允许的最大内存,请使用 -Xmx JVM 参数。以下给出了示例

cordova build android -- --jvmargs='-Xmx4g'

支持以下单位

单位 示例
千字节 k -Xmx2097152k
兆字节 m -Xmx2048m
吉字节 g -Xmx2g

设置版本代码

要更改应用程序生成的 apk 的 版本代码,请在应用程序的 config.xml 文件的 widget 元素中设置 android-versionCode 属性。

如果未设置 android-versionCode,则将使用 version 属性确定版本代码。例如,如果版本为 MAJOR.MINOR.PATCH

versionCode = MAJOR * 10000 + MINOR * 100 + PATCH

如果您的应用程序启用了 cdvBuildMultipleApks Gradle 属性(请参阅 设置 Gradle 属性),则应用程序的版本代码也将乘以 10,以便代码的最后一位可以用来指示构建 apk 的体系结构。无论版本代码是从 android-versionCode 属性获取还是使用 version 生成,都会发生这种乘法。

注意:请注意,添加到项目中的某些插件可能会自动设置此 Gradle 属性。

注意:更新 android-versionCode 属性时,不建议增加从构建的 apk 中获取的版本代码。建议根据 config.xml 文件的 android-versionCode 属性中的值增加代码。这是因为 cdvBuildMultipleApks 属性会导致构建的 apk 中的版本代码乘以 10,因此使用该值会导致您的下一个版本代码是原始版本代码的 100 倍,等等。

签名应用程序

建议首先阅读 Android 的 签名应用程序 文档,因为它包含创建签名所需文件的必要步骤。

使用标志

要签名应用程序,您需要以下参数

参数 标志 描述
密钥库 --keystore 指向可以保存一组密钥的二进制文件的路径
密钥库密码 --storePassword 密钥库的密码
别名 --alias 用于签名的私钥的 ID
密码 --password 指定私钥的密码
密钥库类型 --keystoreType 默认值:根据文件扩展名自动检测
pkcs12 或 jks
包类型 --packageType 默认值:apk 用于调试,bundle 用于发布
指定是构建 APK 还是 AAB(Android 应用程序包)文件。
可接受的值:apkbundle

在使用 Cordova CLI buildrun 命令时,可以在参数中指定上述参数。

注意:您应该使用双 -- 来指示这些是特定于平台的参数。

示例

cordova run android --release -- --keystore=../my-release-key.keystore --storePassword=password --alias=alias_name --password=password --packageType=bundle.

使用 build.json

或者,您可以在构建配置文件(build.json)中指定签名参数。

默认情况下,如果项目的根目录中存在 build.json 文件,则会自动检测并使用它。如果该文件未位于项目的根目录中或有多个配置文件,则必须使用 --buildConfig 命令行参数提供该文件的路径。

示例 build.json 配置文件

{
    "android": {
        "debug": {
            "keystore": "../android.keystore",
            "storePassword": "android",
            "alias": "mykey1",
            "password" : "password",
            "keystoreType": "",
            "packageType": "apk"
        },
        "release": {
            "keystore": "../android.keystore",
            "storePassword": "",
            "alias": "mykey2",
            "password" : "password",
            "keystoreType": "",
            "packageType": "bundle"
        }
    }
}

还支持混合使用命令行参数和 build.json 中的参数。命令行参数中的值优先。这对于在命令行上指定密码很有用。

使用 Gradle

您还可以通过包含一个 .properties 文件并使用 cdvReleaseSigningPropertiesFilecdvDebugSigningPropertiesFile Gradle 属性指向它来指定签名属性(请参阅 设置 Gradle 属性)。

示例文件内容

storeFile=relative/path/to/keystore.p12
storePassword=SECRET1
storeType=pkcs12
keyAlias=DebugSigningKey
keyPassword=SECRET2

storePasswordkeyPassword 属性对于自动签名是必需的。

调试

有关 Android SDK 附带的调试工具的详细信息,请参阅 Android 的调试开发人员文档。此外,Android 的 调试 Web 应用程序 开发人员文档提供了有关调试在 Webview 中运行的应用程序部分的介绍。

在 Android Studio 中打开项目

Cordova-Android 项目可以在 Android Studio 中打开。如果您希望使用 Android Studio 内置的 Android 调试和分析工具,或者如果您正在开发 Android 插件,这将非常有用。

注意:在 Android Studio 中打开项目时,建议不要在 IDE 中编辑代码。在 Android Studio 中编辑将编辑项目 platforms 目录中的代码。它不会更新项目根目录中的代码(www)。这些更改可能会被覆盖。相反,请编辑 www 文件夹,并通过运行 cordova prepare 来复制您的更改。

希望在 Android Studio 中编辑其原生代码的插件开发人员应该在使用 cordova plugin add 将其插件添加到项目时使用 --link 标志。这将在项目的 platforms 目录中创建从插件源目录到插件文件的符号链接。

要在 Android Studio 中打开 Cordova-Android 项目,请执行以下操作

  1. 启动 Android Studio
  2. 单击 打开 按钮 欢迎使用 Android Studio
  3. 导航到项目的 Android 平台目录:(<project-root>/platforms/android
  4. 单击 打开

导入完成后,您应该能够直接从 Android Studio 构建和运行应用程序。

有关更多资源,请参阅

Hello Cordova MainActivity

升级

有关升级 cordova-android 版本的说明,请参阅 本文

生命周期指南

Cordova 和 Android

原生 Android 应用程序通常由一系列用户交互的 活动 组成。活动可以被认为是构成应用程序的各个屏幕;应用程序中的不同任务通常会有自己的活动。每个活动都有自己的生命周期,该生命周期在活动进入和离开用户设备的前台时维护。

相反,Android 平台上的 Cordova 应用程序在嵌入在单个 Android 活动中的 Webview 中执行。此活动的生命周期通过触发的文档事件公开给您的应用程序。这些事件不保证与 Android 的生命周期一致,但它们可以为保存和恢复状态提供指导。这些事件大致映射到 Android 回调,如下所示

Cordova 事件 粗略的 Android 等效项 含义
deviceready onCreate() 应用程序正在启动(不是从后台启动)
pause onPause() 应用程序正在移至后台
resume onResume() 应用程序正在返回前台

大多数其他 Cordova 平台都有类似的生命周期概念,并且在用户设备上发生类似操作时应该触发这些相同的事件。但是,Android 提出了一些独特的挑战,这些挑战有时会由于原生 Activity 生命周期而出现。

是什么让 Android 与众不同?

在 Android 中,操作系统可以选择杀死后台活动以释放资源,如果设备内存不足。不幸的是,当包含应用程序的活动被杀死时,应用程序所在的 Webview 也将被销毁。在这种情况下,应用程序维护的任何状态都将丢失。当用户导航回应用程序时,活动和 Webview 将由操作系统重新创建,但 Cordova 应用程序的状态不会自动恢复。因此,您的应用程序必须了解触发的生命周期事件并维护适当的状态,以确保用户在离开应用程序时不会丢失应用程序中的上下文。

这什么时候会发生?

您的应用程序在离开用户视线时,可能会被操作系统销毁。这种情况主要发生在两种情况下。第一种也是最明显的情况是,当用户按下主页按钮或切换到其他应用程序时。

但是,还存在第二种(更微妙)的情况,某些插件可能会导致这种情况。如上所述,Cordova 应用程序通常被限制在包含 Webview 的单个活动中。但是,在某些情况下,其他活动可能会由插件启动,并暂时将 Cordova 活动推送到后台。这些其他活动通常是为了使用设备上安装的原生应用程序执行特定任务而启动的。例如,Cordova 相机插件 会启动设备上原生安装的任何相机活动,以便拍摄照片。通过这种方式重用已安装的相机应用程序,可以让您的应用程序在用户尝试拍照时感觉更像原生应用程序。不幸的是,当原生活动将您的应用程序推送到后台时,操作系统可能会将其杀死。

为了更清楚地理解第二种情况,让我们以相机插件为例进行说明。假设您有一个应用程序,要求用户拍摄个人资料照片。当一切按计划进行时,应用程序中的事件流程将如下所示

  1. 用户正在与您的应用程序交互,需要拍摄照片
  2. 相机插件启动原生相机活动
    • Cordova 活动被推送到后台(暂停事件被触发)
  3. 用户拍摄照片
  4. 相机活动结束
    • Cordova 活动被移到前台(恢复事件被触发)
  5. 用户被返回到他们离开的应用程序

但是,如果设备内存不足,这种事件流程可能会被打断。如果活动被操作系统杀死,上述事件序列将按如下方式进行

  1. 用户正在与您的应用程序交互,需要拍摄照片
  2. 相机插件启动原生相机活动
    • 操作系统销毁了 Cordova 活动(暂停事件被触发)
  3. 用户拍摄照片
  4. 相机活动结束
    • 操作系统重新创建了 Cordova 活动(deviceready 和恢复事件被触发)
  5. 用户对突然回到应用程序登录屏幕感到困惑

在这种情况下,操作系统在后台杀死了应用程序,并且应用程序没有在生命周期中保持其状态。当用户返回应用程序时,Webview 被重新创建,应用程序似乎从头开始重新启动(因此用户感到困惑)。这种事件序列等同于按下主页按钮或用户切换应用程序时发生的情况。防止上述体验的关键是订阅事件并在活动生命周期中正确维护状态。

尊重生命周期

在上面的示例中,触发的 javascript 事件以斜体显示。这些事件是您保存和恢复应用程序状态的机会。您应该在应用程序的 bindEvents 函数中注册回调,这些回调通过保存状态来响应生命周期事件。您保存的信息以及保存方式由您决定,但您应该确保保存足够的信息,以便在用户返回应用程序时将其恢复到他们离开的位置。

在上面的示例中,还有一个额外的因素只适用于第二种情况(即当插件启动外部活动时)。不仅应用程序的状态在用户完成拍照后丢失了,而且用户拍摄的照片也丢失了。通常,该照片将通过注册到相机插件的回调传递给您的应用程序。但是,当 Webview 被销毁时,该回调将永远丢失。幸运的是,cordova-android 5.1.0 及更高版本提供了一种方法,可以在应用程序恢复时获取该插件调用的结果。

检索插件回调结果 (cordova-android 5.1.0+)

当操作系统销毁被插件推送到后台的 Cordova 活动时,任何挂起的回调也会丢失。这意味着,如果您将回调传递给启动新活动的插件(例如相机插件),则在应用程序重新创建时不会触发该回调。但是,从 cordova-android **5.1.0** 开始,resume 事件的有效负载将包含在活动被销毁之前启动的外部活动的插件请求的任何挂起的插件结果。

resume 事件的有效负载遵循以下格式

{
    action: "resume",
    pendingResult: {
        pluginServiceName: string,
        pluginStatus: string,
        result: any
    }
}

该有效负载的字段定义如下

  • pluginServiceName: 返回结果的插件的名称(例如“Camera”)。这可以在插件的 plugin.xml 文件的 <name> 标签中找到
  • pluginStatus: 插件调用的状态(见下文)
  • result: 插件调用的结果

pendingResult 字段中 pluginStatus 的可能值包括以下内容

  • "OK" - 插件调用成功
  • "No Result" - 插件调用以无结果结束
  • "Error" - 插件调用导致了一些通用错误
  • 其他杂项错误
    • "Class not found"
    • "Illegal access"
    • "Instantiation error"
    • "Malformed url"
    • "IO error"
    • "Invalid action"
    • "JSON error"

注意:插件决定 result 字段中包含的内容以及返回的 pluginStatus 的含义。请参考插件的 API 文档以了解预期结果以及如何使用这些值。

示例

以下是一个简短的示例应用程序,它使用 resumepause 事件来管理状态。它使用 Apache 相机插件作为从 resume 事件有效负载中检索插件调用结果的示例。处理 resumeevent.pendingResult 对象的代码部分需要 cordova-android **5.1.0+**

// This state represents the state of our application and will be saved and
// restored by onResume() and onPause()
var appState = {
    takingPicture: true,
    imageUri: ""
};

var APP_STORAGE_KEY = "exampleAppState";

var app = {
    initialize: function() {
        this.bindEvents();
    },
    bindEvents: function() {
        // Here we register our callbacks for the lifecycle events we care about
        document.addEventListener('deviceready', this.onDeviceReady, false);
        document.addEventListener('pause', this.onPause, false);
        document.addEventListener('resume', this.onResume, false);
    },
    onDeviceReady: function() {
        document.getElementById("take-picture-button").addEventListener("click", function() {
            // Because the camera plugin method launches an external Activity,
            // there is a chance that our application will be killed before the
            // success or failure callbacks are called. See onPause() and
            // onResume() where we save and restore our state to handle this case
            appState.takingPicture = true;

            navigator.camera.getPicture(cameraSuccessCallback, cameraFailureCallback,
                {
                    sourceType: Camera.PictureSourceType.CAMERA,
                    destinationType: Camera.DestinationType.FILE_URI,
                    targetWidth: 250,
                    targetHeight: 250
                }
            );
        });
    },
    onPause: function() {
        // Here, we check to see if we are in the middle of taking a picture. If
        // so, we want to save our state so that we can properly retrieve the
        // plugin result in onResume(). We also save if we have already fetched
        // an image URI
        if(appState.takingPicture || appState.imageUri) {
            window.localStorage.setItem(APP_STORAGE_KEY, JSON.stringify(appState));
        }
    },
    onResume: function(event) {
        // Here we check for stored state and restore it if necessary. In your
        // application, it's up to you to keep track of where any pending plugin
        // results are coming from (i.e. what part of your code made the call)
        // and what arguments you provided to the plugin if relevant
        var storedState = window.localStorage.getItem(APP_STORAGE_KEY);

        if(storedState) {
            appState = JSON.parse(storedState);
        }

        // Check to see if we need to restore an image we took
        if(!appState.takingPicture && appState.imageUri) {
            document.getElementById("get-picture-result").src = appState.imageUri;
        }
        // Now we can check if there is a plugin result in the event object.
        // This requires cordova-android 5.1.0+
        else if(appState.takingPicture && event.pendingResult) {
            // Figure out whether or not the plugin call was successful and call
            // the relevant callback. For the camera plugin, "OK" means a
            // successful result and all other statuses mean error
            if(event.pendingResult.pluginStatus === "OK") {
                // The camera plugin places the same result in the resume object
                // as it passes to the success callback passed to getPicture(),
                // thus we can pass it to the same callback. Other plugins may
                // return something else. Consult the documentation for
                // whatever plugin you are using to learn how to interpret the
                // result field
                cameraSuccessCallback(event.pendingResult.result);
            } else {
                cameraFailureCallback(event.pendingResult.result);
            }
        }
    }
}

// Here are the callbacks we pass to getPicture()
function cameraSuccessCallback(imageUri) {
    appState.takingPicture = false;
    appState.imageUri = imageUri;
    document.getElementById("get-picture-result").src = imageUri;
}

function cameraFailureCallback(error) {
    appState.takingPicture = false;
    console.log(error);
}

app.initialize();

相应的 html

<!DOCTYPE html>

<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Cordova Android Lifecycle Example</title>
    </head>
    <body>
        <div class="app">
            <div>
                <img id="get-picture-result" />
            </div>
            <Button id="take-picture-button">Take Picture</button>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Android 特性

Cordova-Android 平台中的默认 API 级别已升级。在 Android 9 设备上,明文通信现在默认情况下被禁用。

默认情况下,HTTP、FTP 等将拒绝应用程序使用明文流量的请求。避免明文流量的主要原因是缺乏机密性、真实性和防篡改保护;网络攻击者可以窃听传输的数据,也可以在不被发现的情况下修改数据。您可以在 Android 开发人员文档 中了解更多关于 android:usesCleartextTraffic 或任何其他 Android 应用程序元素设置的信息。

要再次允许明文通信,请在 config.xml 文件中将应用程序标签上的 android:usesCleartextTraffic 设置为 true

<platform name="android">
  <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
      <application android:usesCleartextTraffic="true" />
  </edit-config>
</platform>

您还需要在同一个 config.xml 中的 widget 标签中添加 Android XML 命名空间 xmlns:android="http://schemas.android.com/apk/res/android"

示例

<widget id="io.cordova.hellocordova" version="0.0.1" android-versionCode="13" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="https://cordova.net.cn/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
</widget>

Android 清单信息

您可以在 Android 开发人员文档 中了解更多关于 Android 清单信息的信息。

测试活动生命周期

Android 提供了一个开发人员设置,用于测试低内存情况下的活动销毁。在设备或模拟器的“开发者选项”菜单中启用“不保留活动”设置,以模拟低内存情况。您应该始终启用此设置进行一定程度的测试,以确保您的应用程序正确维护状态。