应用基础知识

您可以使用 Kotlin、Java 编程语言和 C++ 语言编写 Android 应用。Android SDK 工具编译 将您的代码以及任何数据和资源文件导入 APK 或 Android App Bundle。

Android 软件包(即带有 .apk 后缀的归档文件)包含 运行时所需的 Android 应用的内容,它是由 Android 提供支持的文件 安装您应用的设备。

Android App Bundle 是一种带有 .aab 后缀的归档文件,其中包含 Android 应用项目的内容,包括 运行时。AAB 是一种发布格式,无法安装在 Android 设备上。它 将 APK 生成和签名推迟到后续阶段。

通过 Google 分发应用时 例如,Google Play 的服务器会生成经过优化的 APK,其中仅包含资源和 请求安装应用的特定设备所需的全部代码。

每个 Android 应用都处于各自的安全沙盒中,受到 以下 Android 安全功能:

  • Android 操作系统是一种多用户 Linux 系统,其中的每个应用都是一个 不同用户
  • 默认情况下,系统会为每个应用分配一个唯一的 Linux 用户 ID,该 ID 仅供 并且应用是未知的系统会为文件夹中的所有文件设置权限 应用,以便只有分配给该应用的用户 ID 才能访问它们。
  • 每个进程都有自己的虚拟机 (VM),因此应用的代码 。
  • 默认情况下,每个应用都在自己的 Linux 进程中运行。Android 系统启动 这个过程中 然后关闭相应进程 不再使用 或系统必须为其他应用恢复内存时。

Android 系统实现了最小权限原则。也就是说, 默认情况下,每个应用都只能访问执行其工作和 不用再说了。这将创建一个非常安全的环境,在该环境中应用无法访问 权限。

不过,应用还可以通过一些方式 与其他应用共享数据 应用来访问系统服务:

  • 可以安排两个应用共享同一个 Linux 用户 ID,在这种情况下 就能访问彼此的文件为了节约系统资源, 也可以安排在同一 Linux 进程中运行并共享同一虚拟机。通过 应用也必须使用相同的证书进行签名。
  • 应用可以请求访问设备数据的权限,例如设备的 位置信息、相机和蓝牙连接。用户 来明确授予这些权限。有关权限的详细信息,请参阅 Android 中的权限

本文档的其余部分将介绍以下概念:

  • 用于定义应用的核心框架组件
  • 您声明组件和所需设备的清单文件 功能 应用。
  • 与应用代码分离并允许您的应用使用的资源 针对各种设备配置妥善优化其行为。

应用组件

应用组件是 Android 应用的基本构建块。每个 组件是一个入口点,系统或用户可通过该入口点进入您的应用。部分 组件依赖于其他组件。

应用组件有四种类型:

  • 活动
  • 服务
  • 广播接收器
  • content provider

每种类型都有不同的用途 并且具有定义组件的创建和销毁方式的独特生命周期。 以下部分将介绍应用组件的四种类型。

活动
activity 是与用户交互的入口点。它代表 有一个界面例如: 一个电子邮件应用可能有一个 activity 显示 电子邮件、一个用于撰写电子邮件的 Activity 以及用于阅读电子邮件的另一个 Activity。虽然 这些 activity 协同工作,在电子邮件应用中形成统一的用户体验,每个 activity 相互独立

其他应用可以启动其中任一应用 activity(如果电子邮件应用允许)。例如,相机应用可能会启动 电子邮件应用中的 activity,用于撰写新电子邮件,让用户共享图片。

Activity 有助于完成系统和应用程序之间的以下重要交互:

  • 跟踪用户当前关心的内容(屏幕上显示的内容),以便 系统会继续运行托管 activity 的进程。
  • 了解之前用过的进程包含用户可能返回到的已停止 activity 并更加重视这些进程,确保它们始终可用。
  • 帮助应用处理其进程被终止,以便用户能够返回到 activity 恢复之前的状态
  • 提供一种方法,让应用能够在彼此之间实现用户流,并让系统能够 协调这些流。主要示例是共享。

您可以将 activity 实现为 Activity 类的子类。有关 Activity 类的相关信息,请参阅 activity 简介

服务
服务是用于保持应用在后台运行的通用入口点 可能出于各种原因它是一种在后台运行的组件,用于执行长时间运行的 操作或为远程进程执行工作。服务不提供界面。

对于 例如,当用户使用其他应用时,服务可能会在后台播放音乐;或者 它可以在不阻止用户与 activity 的互动的情况下通过网络提取数据。另一个 组件(例如 activity)可以启动服务并让服务运行或绑定到服务 并与之互动

有两种类型的服务可以指示系统如何管理应用:已启动的服务和 绑定服务

已启动的服务会告知系统使其保持运行状态,直到其工作完成为止。 这可能是在后台同步一些数据,或者在用户离开应用后继续播放音乐。 在后台同步数据或播放音乐代表了不同类型的开始 服务,系统处理它们的方式有所不同:

  • 音乐播放是用户能直接感知到的内容,应用会将此信息传达给 来指示系统运行该程序 运行该程序的用户在这种情况下,系统会优先保留该服务的 进程运行,因为如果退出,用户的体验会很糟糕。
  • 用户无法直接知晓常规后台服务, 系统可以更自由地管理自己的进程。它可能会杀死它, 如果系统需要 RAM 用于存储性能更重要的任务, 用户关心的紧迫问题。

绑定服务之所以运行,是因为某个其他应用(或系统)已表示想要使用 服务。绑定服务向其他进程提供 API,而系统会 这些进程之间存在依赖关系因此如果进程 A 因此系统知道需要让进程 B 及其服务保持运行状态。此外,如果 进程 A 是用户关心的内容,然后它就知道将进程 B 视为 用户关心的内容

由于它们具有灵活性,因此 各种高级系统概念的基础组件。动态壁纸、通知 监听器、屏保、输入法、无障碍服务以及许多其他核心系统功能 均以服务的形式构建,由应用实现,系统会在它们运行时进行绑定。

服务作为 Service 的子类实现。更多信息 有关 Service 类的信息,请参阅 服务概览

注意:如果您的应用以 Android 5.0(API 级别 21)或更高版本为目标平台, 请使用 JobScheduler 类来调度操作。JobScheduler 具有 通过以最优方式调度作业来减少耗电量,从而节省电量 以及通过使用 Doze API 完成。 如需详细了解如何使用此类,请参阅 JobScheduler 参考文档。

广播接收器
广播接收器是一个组件,可让系统向 应用,以便应用能够响应系统级广播 通知。由于广播接收器是应用的另一个明确定义的条目, 甚至可以向当前未运行的应用传递广播。

例如,应用可以 设置闹钟以发布通知,以告知用户即将发生的事件。 由于闹钟已传送给应用中的 BroadcastReceiver,因此应用无需 在闹钟响起之前保持运行状态

许多广播都是从系统发起的,例如宣布屏幕关闭的广播, 电量不足,或已拍照。 应用也可以发起广播,例如告知其他应用 部分数据会下载到设备,可供他们使用。

尽管广播 接收方不显示界面,他们可以创建状态栏通知 在发生广播事件时提醒用户。但更常见的是,广播接收器是 只是通往其他组件的网关,旨在执行极少量的工作。

例如,广播接收器可能会调度 JobService,以���据 ��用 JobScheduler 创建事件。 广播接收器通常涉及应用相互交互,因此请务必了解 安全隐患。

广播接收器作为 BroadcastReceiver 的子类实现, 并且每个广播都作为 Intent 对象进行传送。如需更多信息 请参阅 BroadcastReceiver 类。

content provider
content provider 管理一组共享的应用数据,供您存储这些数据 文件系统中、SQLite 数据库、Web 中或任何其他永久性存储空间中 您的 应用可以访问的内容。其他应用可以通过内容提供程序查询或修改 (如果内容提供者允许的话)。

例如,Android 系统提供的内容 管理用户联系信息的提供程序。任何具有适当 权限可以查询内容提供程序,例如使用 ContactsContract.Data,用于读取和写入 特定人员。

我们很容易将 content provider 视为数据库上的抽象,因为 针对这种常见情况,这些 API 内置了大量的 API 和支持。不过,它们与 从系统设计的角度来看。

对系统而言,content provider 是应用的入口点,用于发布已命名的数据项。 使用 URI scheme 标识。因此,应用可以决定如何将其包含的数据映射到 URI 命名空间,然后将这些 URI 分发给其他实体,这些实体进而可以使用它们来访问 数据。系统可在管理应用时执行以下一些特定操作:

  • 分配 URI 不需要应用保持运行,因此 URI 可在其 退出。系统只需确保所有者应用 在从相应的 URI 检索应用数据时,它仍会运行。
  • 这些 URI 还提供了重要的精细安全模型。例如, 应用可以将其所含图片的 URI 放到剪贴板中,但保留其内容 提供程序会被锁定,这样其他应用就无法自由访问它。当另一个应用尝试 访问剪贴板上的 URI,系统可以让该应用 通过临时的 URI 权限授权访问数据 以便只访问该 URI 后面的数据,而不需要访问第二个应用中的其他任何内容。

内容提供程序也适用于读取和写入 应用,未分享。

content provider 是作为 ContentProvider 的子类实现的。 并且必须实现一组标准的 API,使其他应用能够 交易。有关详情,请参阅内容提供方开发者 指南。

Android 系统设计的独特之处在于,任何应用都可以启动另一个 应用组件。例如,如果您希望用户捕获 可能还有其他应用可以做到这一点,而您的 应用可以使用它,而无需开发 activity 自行拍摄照片。你不会 需要加入甚至链接到相机应用中的代码。 您可以改为在相机应用中启动 照片。完成后,系统甚至会将照片返回给您的应用,以便您使用。对于用户 就好像相机确实是应用的一部分。

当系统启动某个组件时,会启动该应用的进程(如果不是 并实例化组件所需的类。例如,如果您的 应用启动相机应用中拍摄照片的 activity,该 activity 在属于相机应用的进程(而非您应用的进程)中运行。 因此,与大多数其他系统上的应用不同,Android 应用没有单一条目, 点:没有 main() 函数。

由于系统在单独的进程中运行每个应用,且其文件权限 限制对其他应用的访问,那么您的应用无法从 另一个应用。但 Android 系统可以。要在 您需要向系统传递一条消息,指明您的 intent 启动特定组件。系统随后便会为您启动该组件。

启用组件

称为 intent 的异步消息会激活四种组件类型中的三种:Activity、服务和 广播接收器。 intent 会在运行时将各个组件相互绑定。您可以把它们想象成 用作从其他组件请求操作的信使,无论该组件属于 分发给您的应用或其他应用

使用 Intent 对象创建 intent,该对象定义了发送给 激活特定组件(显式 intent)或特定类型的组件 (隐式 intent)。

对于 activity 和服务,intent 会定义要执行的操作,例如 view发送内容,并可能指定要操作的数据的 URI,以及其他 组件可能需要知悉。

例如,intent 可能会传达对 显示图片或打开网页。在某些情况下,您可以启动 activity 接收结果,在这种情况下,activity 也会返回 返回 Intent。您还可以发出一个 intent 用户选择一位个人联系人并将其返回给您。返回 intent 包括 指向所选联系人的 URI。

对于广播接收器,intent 会定义 广播通知。例如,指示设备电池电量不足的广播 仅包含指示“电池电量不足”的已知操作字符串。

与 activity、Service 和广播接收器不同,content provider 与 在被来自 ContentResolver 的请求定位时激活。内容 解析器处理与 content provider 以及该组件进行的所有直接事务, 通过提供程序执行事务时,调用 ContentResolver 对象。出于安全原因,这在 API 和 API 之间的 content provider 以及请求信息的组件。

每种组件都有不同的启动方法:

  • 你可以启动一项活动,也可以让它 将 Intent 传递给 startActivity() 或者,当您希望 activity 返回结果时, startActivityForResult()
  • 在 Android 5.0(API 级别 21)及更高版本中,您可以使用 JobScheduler 类来调度操作。 对于��期的 Android 版本 或为某项正在进行的服务提供新说明, 将 Intent 传递给 startService()。 您可以通过将 Intent 传递给 bindService()
  • 您可以通过向如下方法传递 Intent 来发起广播: sendBroadcast()sendOrderedBroadcast()
  • 您可以通过调用 query()ContentResolver上。

如需详细了解如何使用 intent,请参阅 intent 和 intent 过滤器文档。 以下文档详细介绍了如何激活特定组件: activity 简介 服务概览BroadcastReceiverContent Provider

清单文件

在 Android 系统可以启动应用组件之前,系统必须知道 通过读取应用的清单文件 AndroidManifest.xml 确定该组件是否存在。 您的应用在此文件中声明了其所有组件,该文件位于 app project 目录。

除了声明应用的组件、 例如:

  • 确定应用需要的任何用户权限,例如互联网访问权限或 对用户联系人的读取权限。
  • 声明最低数量 API 级别 这取决于应用使用的 API。
  • 声明应用使用或需要的硬件和软件功能,例如相机; 蓝牙服务或多点触控屏幕。
  • 声明应用需要关联的 API 库(Android 框架除外) API),例如 Google 地图库

声明组件

清单的主要任务是告知系统有关应用组件的信息。对于 例如,清单文件可以按如下方式声明 activity:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:icon="@drawable/app_icon.png" ... >
        <activity android:name="com.example.project.ExampleActivity"
                  android:label="@string/example_label" ... >
        </activity>
        ...
    </application>
</manifest>

<application>中 元素,android:icon 属性指向一个图标对应的资源,该图标用于标识 应用。

<activity> 元素中, android:name 属性用于指定 Activity 子类,而 android:label 属性指定字符串 用作 activity 的用户可见标签。

您必须使用以下元素声明所有应用组件:

包含在来源中但未声明的 activity、服务和 content provider 对系统不可见,因此也永远无法运行。不过, 广播 接收器可以在清单中声明,也可以在代码中动态创建为 BroadcastReceiver 对象,并通过调用 registerReceiver()

如需详细了解如何为应用构建清单文件,请参阅应用清单概览

声明组件功能

激活组件部分所述,您可以使用 Intent,用于启动 activity、服务和广播接收器。 您需要执行此操作 方法是在 intent 中使用组件类名称显式命名目标组件。 您还可以使用隐式 intent, 说明要执行的操作类型,以及(可选)您要 执行操作隐式 intent 可让系统查找设备上的组件 可以执行 操作并启动它如果有多个组件可执行 intent,用户选择使用哪一个。

注意:如果您使用 intent 启动 Service,请使用 露骨内容 intent。使用隐式 Intent 启动服务是一种 安全隐患,因为您无法确定哪些服务会响应 intent 用户也就无法看到哪项服务已启动从 Android 5.0(API 级别 21)开始,系统 如果调用 bindService(),则会抛出异常 具有隐式 intent。请勿为您的服务声明 intent 过滤器。

系统会通过比较 intent 过滤器收到的 intent 发送到 。

在应用的清单中声明 activity 时,您可以选择添加 声明 activity 功能以便响应 intent 的 intent 过滤器 从其他应用中移除。为此,您需要 添加 <intent-filter> 元素作为组件声明元素的子元素。

例如,如果您构建一个电子邮件应用,其中包含用于撰写新电子邮件的 activity,则可以 声明一个 intent 过滤器以响应“send”发送新电子邮件的意图 如以下示例中所示:

<manifest ... >
    ...
    <application ... >
        <activity android:name="com.example.project.ComposeEmailActivity">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <data android:type="*/*" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

如果其他应用创建包含 ACTION_SEND 操作的 intent 并将其传递给 startActivity(), 系统可能会启动您的 activity,以便用户草稿和发送 电子邮件。

如需详细了解如何创建 intent 过滤器,请参阅 intent 和 intent 过滤器文档。

声明应用要求

Android 设备多种多样,并不是所有的设备都能提供 相同的特性和功能。阻止应用安装在设备上 缺少应用所需的功能,那么请务必明确定义一个配置文件, 通过在 清单文件

其中大多数声明仅供参考。系统不读取 但 Google Play 等外部服务会读取这些文件以便进行过滤 。

例如,假设您的应用需要相机,并使用 Android 8.0(API 级别 26)中引入的 API。 您必须声明这些要求。 minSdkVersiontargetSdkVersion 的值在 应用模块的 build.gradle 文件:

android {
  ...
  defaultConfig {
    ...
    minSdkVersion 26
    targetSdkVersion 29
  }
}

注意:请勿设置 minSdkVersiontargetSdkVersion, 它们在构建过程中会被 Gradle 覆盖。如需了解详情,请参阅 指定 API 级别要求

您可以在应用的清单文件中声明相机功能:

<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    ...
</manifest>

对于这些示例中所示的声明,具有 摄像头或 低于 8.0 的 Android 版本无法从 Google Play 安装您的应用。 不过,您也可以声明您的应用使用相机,但不使用相机 require 它。为此,您可以设置 required 属性设为 false,在运行时检查是否 设备配有摄像头,并根据需要停用所有摄像头功能。

详细了解如何管理应用与不同设备的兼容性 请参阅设备兼容性概览

应用资源

Android 应用不仅仅包含代码,它需要 例如图片、音频文件以及与视觉内容相关的所有内容 应用的呈现方式例如,您可以定义动画、菜单、样式、颜色 以及包含 XML 文件的 activity 界面布局。

使用应用资源可以轻松 在不修改代码的情况下更新应用的各种特性。正在提供 您可以利用一组备用资源针对各种不同需求 设备配置,例如不同的语言和屏幕尺寸。

对于您包含在 Android 项目中的每一项资源,SDK 构建工具都会定义一个 整数 ID,可用于从应用代码中或 XML 中定义的其他资源。例如,如果您的应用包含名为 logo.png(保存在 res/drawable/ 目录中),SDK 工具会生成 名为 R.drawable.logo 的资源 ID。此 ID 映射到应用特定的整数 您可以使用 引用该图片并将其插入您的界面中。

提供独立于源代码的资源的最重要方面之一 能够为不同设备提供备用资源 配置。

例如,通过在 XML 中定义界面字符串,您可以将 将字符串转换成其他 并将这些字符串保存在单独的文件中。然后,Android 会将 相应的语言字符串 根据语言限定符向您的界面添加样式 附加到资源目录名称后面,例如 res/values-fr/ 表示法语字符串 值以及用户的语言设置。

Android 支持为备用资源使用许多限定符。通过 限定符是一个简短��字符串,包含在资源目录名称中, 定义这些资源所使用的设备配置。

对于 例如,您可以根据 设备的屏幕方向和尺寸。当设备屏幕为纵向(长型)时 您可能想要一种具有垂直排列按钮的布局,但当屏幕处于 横向(宽)方向,那么您可能需要将按钮水平对齐。更改布局 您可以定义两种布局,并应用合适的 限定符添加到每个布局的目录名称中。然后,系统会自动应用适当的 具体取决于当前设备的屏幕方向。

如需详细了解可以包含在应用中的各种资源,以及如何 为不同的设备配置创建备用资源,请参阅应用资源概览。接收者 详细了解最佳实践以及如何设计稳健且达到生产质量的应用。 请参阅应用架构指南

其他资源

如需通过视频和代码教程了解 Android 开发,请参阅 使用 Kotlin 开发 Android 应用 Udacity 课程。

继续阅读以下内容:

intent 和 intent 过滤器
了解如何使用 Intent API 激活应用组件,例如 activity 和服务,以及如何让应用组件 可供其他应用使用
activity 简介
了解如何创建 Activity 类的实例。 它可在应用中提供一个具有界面的独特屏幕。
应用资源概览
了解如何设计 Android 应用的结构,以便将应用资源与 应用代码,包括如何为特定设备提供备用资源 配置。

其他建议:

设备兼容性概览
了解 Android 如何在不同类型的设备上运作,以及 如何针对每种设备优化您的应用,或如何限制应用的可用性 不同的设备
Android 中的权限
了解 Android 如何通过权限限制应用对某些 API 的访问权限 该系统需要用户同意您的应用才能使用这些 API。