android应用基础知识
来自于官方应用基础知识摘抄
可以使用Kotlin,Java C++编写Android应用,Android SDK工具会将你的代码以及任何数据和资源文件编译成APK或Android App Bundle。
Android软件包是一种带有.apk后缀归档文件,其中包含运行时所需要得Android应用得内容,也是Android设备用来安装得应用文件。
Android App Bundle 是一种后缀为 .aab
的归档文件,其中包含 Android 应用项目的内容,包括运行时不需要的一些其他元数据。AAB 是一种发布格式,无法在 Android 设备上安装。这会将 APK 生成和签名推迟到以后的阶段。
例如,通过 Google Play 分发您的应用时,Google Play 的服务器会生成经过优化的 APK,其中仅包含请求安装应用的特定设备所需的资源和代码。
每个 Android 应用都处于各自的安全沙盒中,并受到以下 Android 安全功能的保护:
- Android 操作系统是一种多用户 Linux 系统,其中的每个应用都是一个不同的用户。
- 默认情况下,系统会为每个应用分配一个唯一的 Linux 用户 ID,该 ID 仅供系统使用,应用不知道。系统会为应用中的所有文件设置权限,以便只有分配给该应用的用户 ID 才能访问这些文件。
- 每个进程都有自己的虚拟机 (VM),因此一个应用的代码与其他应用是隔离开来的。
- 默认情况下,每个应用都在自己的 Linux 进程中运行。Android 系统会在需要执行应用的任何组件时启动该进程,然后在不再需要该进程或系统必须为其他应用恢复内存时关闭该进程。
Android 系统实现了最小权限原则。也就是说,默认情况下,每个应用都只能访问执行其工作所需的组件,而不能访问其他组件。这样会创建一个非常安全的环境,在该环境中,应用无法访问系统其未获得权限的部分。
不过,应用可以通过一些方式与其他应用共享数据,以及访问系统服务:
- 可以安排两个应用共享同一个 Linux 用户 ID,在这种情况下,它们可以访问彼此的文件。为了节省系统资源,您还可以安排具有相同用户 ID 的应用在同一 Linux 进程中运行并共享同一虚拟机。这些应用还必须使用相同的证书进行签名。
- 应用可以请求访问设备数据(如设备的位置信息、相机和蓝牙连接)的权限。用户必须明确授予这些权限。如需详细了解权限,请参阅 Android 中的权限。
本文档的其余部分将介绍以下概念:
- 用于定义应用的核心框架组件
- 您在其中声明组件和应用所需设备功能的清单文件。
- 与应用代码分开且能让应用针对各种设备配置适当优化其行为的资源。
应用组件
应用组件是 Android 应用的基本构建块。每个组件都是一个入口点,系统或用户可通过它进入您的应用。有些组件会依赖于其他组件。
应用组件有以下四种类型:
- Activity
- 服务
- 广播接收器
- Content provider
每种类型都有不同的用途,并且具有用于定义组件创建和销毁方式的不同生命周期。以下部分将介绍应用组件的四种类型。
activity
activity 是与用户交互的入口点。它表示具有界面的单个屏幕。例如,电子邮件应用可能具有一个显示新电子邮件列表的 Activity、一个用于撰写电子邮件的 Activity 以及另一个用于阅读电子邮件的 Activity。虽然这些 activity 协同工作以在电子邮件应用中形成统一的用户体验,但每个 activity 都独立于其他 activity。
如果电子邮件应用允许,其他应用可以启动其中任何一个 activity。例如,相机应用可能会在电子邮件应用中启动用于撰写新电子邮件的 activity,以便用户分享照片。
Activity 有助于完成系统和应用程序之间的以下重要交互:
- 跟踪用户当前关注的内容(屏幕上的内容),以便系统继续运行托管 Activity 的进程。
- 了解先前使用的进程包含用户可能返回到的已停止 activity,并更高地确定这些进程的优先级,以确保这些进程保持可用。
- 帮助应用处理终止其进程的情况,以便用户能够返回 Activity 并恢复其先前的状态。
- 提供一种方式,让应用实现彼此之间的用户流,并让系统协调这些流。这方面的一个主要示例是分享。
您可以将 activity 作为 Activity
类的子类来实现。如需详细了解 Activity
类,请参阅 activity 简介。
服务
服务是一种通用入口点,用于出于各种原因使应用在后台运行。它是一个在后台运行的组件,用于执行长时间运行的操作或为远程进程执行作业。服务不提供界面。
例如,当用户位于其他应用中时,服务可能在后台播放音乐,或者通过网络提取数据,而不会阻止用户与 activity 的互动。另一个组件(如 activity)可以启动服务,让其运行或绑定到服务以与其进行交互。
有两种服务可以告知系统如何管理应用:已启动服务和绑定服务。
已启动的服务会告知系统让它们保持运行,直到工作完成为止。这可能是在后台同步一些数据,或者在用户离开应用后继续播放音乐。在后台同步数据或播放音乐表示不同类型的已启动服务,系统会以不同的方式处理这些服务:
- 音乐播放是用户能够直接感知到的,应用会通过指示自己想要位于前台来将这一情况传达给系统,同时通过通知告知用户其正在运行。在这种情况下,系统会优先让该服务的进程保持运行,因为如果这些服务的进程消失,用户的体验会很糟糕。
- 常规后台服务不是用户直接注意到的,因此系统可以更自由地管理其进程。如果服务需要使用 RAM 来处理用户更关注的事情,它可能会被终止,稍后会重启服务。
运行绑定服务是因为某些其他应用(或系统)已表示想要使用该服务。绑定服务向其他进程提供 API,而系统知道这些进程之间存在依赖关系。因此,如果进程 A 绑定到进程 B 中的服务,则系统知道需要让进程 B 及其服务保持为 A 运行。此外,如果进程 A 是用户关心的内容,它就会将进程 B 视为用户也关心的内容。
由于服务具有灵活性,因此对于各种更高级别的系统概念而言,服务都是有用的构建块。动态壁纸、通知监听器、屏保、输入法、无障碍服务和许多其他核心系统功能都是以服务的形式构建的,供应用实现,并且系统会在运行时与之绑定。
服务作为 Service
的子类实现。如需详细了解 Service
类,请参阅 服务概览。
广播接收器
广播接收器是一种组件,可让系统在常规用户流之外向应用传递事件,以便应用能够响应系统级广播通知。由于广播接收器是应用中的另一个明确定义的条目,因此系统甚至可以将广播传送到当前未运行的应用。
例如,应用可以安排闹钟来发布通知,告知用户即将进行的活动。由于闹钟是传递给应用中的 BroadcastReceiver
,因此在闹钟响起之前,应用无需继续运行。
很多广播都源自系统,例如通知屏幕已关闭、电池电量不足或已拍摄照片的广播。应用还可以发起广播,例如告知其他应用某些数据已下载到设备上并可供其使用。
虽然广播接收器不会显示界面,但它们可以创建状态栏通知,以便在广播事件发生时提醒用户。但广播接收器更常见的用途只是作为通向其他组件的通道,旨在执行极少量的工作。
例如,广播接收器可能会使用 JobScheduler
根据事件安排 JobService
来执行一些工作。广播接收器常常涉及应用之间相互交互,因此在设置广播接收器时,请务必注意安全隐患。
广播接收器作为 BroadcastReceiver
的子类实现,并且每条广播都作为 Intent
对象进行传送。如需了解详情,请参阅 BroadcastReceiver
类。
content provider
content provider 管理一组共享的应用数据,您可以将这些数据存储在文件系统、SQLite 数据库、Web 或应用可以访问的任何其他永久性存储位置。如果 content provider 允许,其他应用可以通过 content provider 查询或修改数据。
例如,Android 系统提供用于管理用户联系信息的 content provider。任何具有适当权限的应用都可以查询 content provider(例如使用 ContactsContract.Data
),以读取和写入有关特定人员的信息。
人们很容易将 content provider 视为数据库上的抽象,因为其中内置了许多 API 和支持来应对这种常见情况。不过,从系统设计的角度来看,它们的核心用途不同。
在系统中,content provider 是应用的入口点,用于发布由 URI 架构标识的已命名数据项。因此,应用可以决定如何将其包含的数据映射到 URI 命名空间,从而将这些 URI 分发给其他实体,而其他实体反过来又可以使用它们来访问数据。这可让系统在管理应用时执行以下特殊操作:
- 分配 URI 不需要应用保持运行状态,因此 URI 在其所属应用退出后可以保留。系统只需确保拥有的应用在从相应的 URI 检索应用数据时仍在运行即可。
- 这些 URI 还提供重要的精细安全模型。例如,应用可将其所拥有的图像的 URI 放到剪贴板,但将其 content provider 保持锁定状态,以便其他应用无法自由访问该图像。当第二个应用尝试访问剪贴板上的该 URI 时,系统可以允许该应用使用临时的 URI 权限授予访问数据,这样它就仅访问该 URI 后方的数据,而不访问第二个应用中的任何其他数据。
content provider 也适用于读取和写入您的应用不共享的私有数据。
content provider 作为 ContentProvider
的子类实现,并且必须实现一组使其他应用能够执行事务的标准 API。如需了解详情,请参阅内容提供程序开发者指南。
Android 系统设计的独特之处在于,任何应用都可以启动其他应用的组件。例如,如果您希望用户使用设备的相机拍摄照片,可能有另一个应用可以执行此操作,而您的应用可以使用该应用,而无需开发 activity 自行拍摄照片。您无需整合甚至链接到相机应用中的代码,而是可以在相机应用中启动拍摄照片的 activity。完成后,系统甚至会将照片返回给您的应用,以便您使用。对用户而言,就好像相机是您应用的一部分。
当系统启动某个组件时,它会启动该应用的进程(如果尚未运行),并实例化该组件所需的类。例如,如果您的应用启动相机应用中拍摄照片的 activity,则该 activity 会在属于相机应用的进程(而不是应用的进程)中运行。因此,与大多数其他系统上的应用不同,Android 应用没有单个入口点,即没有 main()
函数。
由于系统在单独的进程中运行每个应用,且其文件权限会限制对其他应用的访问,因此您的应用无法直接启动其他应用中的组件,但 Android 系统可以。如需激活其他应用中的组件,您需要向系统传递一条消息,指明您用于启动特定组件的 intent。系统随后便会为您启动该组件。
清单文件
系统必须先读取应用的清单文件 AndroidManifest.xml
,确认组件存在,然后 Android 系统才能启动应用组件。您的应用会在此文件(位于应用项目目录的根目录下)中声明其所有组件。
除了声明应用的组件之外,清单还会执行一些其他操作,例如:
- 识别应用需要的任何用户权限,例如互联网访问权限或对用户联系人的读取权限。
- 根据应用使用的 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 的
<activity>
元素 - 服务的
<service>
元素 - 广播接收器的
<receiver>
元素 - content provider 的
<provider>
元素
您包含在源代码中但未声明的 activity、服务和 content provider 对系统不可见,因此它们永远也不会运行。不过,广播接收器可以在清单中声明,也可以在代码中动态创建为 BroadcastReceiver
对象,并通过调用 registerReceiver()
在系统中注册。
如需详细了解如何为应用构建清单文件,请参阅应用清单概览。
声明组件功能
如激活组件部分所述,您可以使用 Intent
启动 activity、服务和广播接收器。为此,您可以在 intent 中使用组件类名明确命名目标组件。您还可以使用隐式 intent,该 intent 描述要执行的操作的类型,以及(可选)要对其执行操作的数据。隐式 intent 使系统能够在设备上找到可执行操作的组件并启动它。如果有多个组件可以执行 intent 所描述的操作,用户可选择使用哪一个。
应用资源
Android 应用不仅仅由代码组成。它需要与源代码分离的资源,例如图片、音频文件以及与应用的视觉呈现有关的任何内容。例如,您可以使用 XML 文件定义 activity 界面的动画、菜单、样式、颜色和布局。
借助应用资源,您无需修改代码即可轻松更新应用的各种特性。通过提供一组备用资源,您可以针对各种设备配置(例如不同的语言和屏幕尺寸)优化应用。
对于您在 Android 项目中添加的每项资源,SDK 构建工具都会定义一个唯一的整数 ID,您可以利用该 ID 来引用应用代码或 XML 中定义的其他资源中的资源。例如,如果您的应用包含名为 logo.png
的图片文件(保存在 res/drawable/
目录中),则 SDK 工具会生成名为 R.drawable.logo
的资源 ID。此 ID 映射到一个应用特定的整数,您可以使用它来引用图片并将其插入界面中。
提供独立于源代码的资源,其中一个最重要的方面是能够为不同的设备配置提供备用资源。
例如,通过使用 XML 定义界面字符串,您可以将字符串翻译成其他语言,并将这些字符串保存在单独的文件中。然后,Android 会根据您附加到资源目录名称的语言限定符将适当的语言字符串应用到界面,例如 res/values-fr/
表示法语字符串值,以及用户的语言设置。
Android 支持许多备用资源的限定符。限定符是包含在资源目录名称中的简短字符串,用于定义这些资源使用的设备配置。
例如,您可以根据设备的屏幕方向和尺寸为 activity 创建不同的布局。当设备屏幕为纵向(高)方向时,您可能需要一个按钮垂直排列的布局;但当屏幕处于横向(宽)方向时,您可能需要按钮水平对齐。如需根据屏幕方向更改布局,您可以定义两个布局,并为每个布局的目录名称应用适当的限定符。然后,系统会根据当前的设备屏幕方向自动应用适当的布局。
如需详细了解可在应用中添加的不同类型的资源,以及如何为不同的设备配置创建备用资源,请参阅应用资源概览。如需详细了解最佳实践,以及如何设计稳健且达到生产质量的应用,请参阅应用架构指南。
其他资源
如需使用视频和代码教程学习 Android 开发,请参阅使用 Kotlin 开发 Android 应用 Udacity 课程。