1. 简介
构建内容
在此 Codelab 中,您将构建 Android 应用来检测用户的睡眠时间。该应用将:
- 请求权限
- 注册 Android Sleep API
- 检索 API 事件并在界面上予以显示
- 不再需要该 API 时取消注册
所需条件
- 已安装 Android Build Tools v21 或更高版本的最新版 Android Studio
- 搭载 Android 10(API 级别 29)或更高版本的设备
2. 准备工作
克隆初始项目代码库
为帮助您尽快入门,我们准备了一个初始项目,您可以在此项目的基础上进行构建。通过在终端/命令行中输入 git --version
,检查您是否已安装 git。如果尚未安装,请按照这些说明进行安装。然后,只需运行以下命令即可克隆项目。
git clone https://github.com/android/codelab-android-sleep/
导入项目
启动 Android Studio,然后在欢迎屏幕中选择“Open an existing Android Studio project”,以打开项目目录。
项目加载完成后,您可能还会看到一条提醒,指出 Git 将不会跟踪所有本地更改。您可以点击右上角的 Ignore 或 X。(您所做的任何更改都不会保存到 Git 代码库中。)
如果您采用的是 Android 视图,那么在项目窗口的左上角应该会看到类似下图所示的内容。(如果您采用的是 Project 视图,那么需要展开项目才能看到这些内容。)
您可以看到两个文件夹图标(start
和 complete
)。它们都称为“模块”。
请注意,首次打开项目时,Android Studio 可能需要数秒时间在后台编译项目。在此期间,您会在 Android Studio 底部的状态栏中看到一个旋转图标:
建议您等待此过程完成后再更改代码。这样,Android Studio 就可以提取所有必要的组件。
此外,如果您看到“Reload for language changes to take effect?”的提示或类似内容,请选择“Yes”。
了解初始项目
现在,您已经完成准备工作,可以开始添加运动状态识别功能了。我们将使用 start
模块,这是此 Codelab 的起点。换句话说,您将在每个步骤向 start
中添加代码。
complete
模块可用于检查您的工作,或在您遇到问题时提供参考。
关键组件概览:
MainActivity.kt
:用户启动应用时渲染应用主屏幕。SleepReceiver.kt
:从 API 中提取睡眠事件并将其存储到数据库中。BootReceiver.kt
:在设备启动完成后重新注册 Sleep API,以便继续监听 Sleep API 事件。
运行初始项目
现在,我们来运行应用。
- 将您的 Android 设备连接到计算机。
- 在工具栏中,从下拉选择器中选择
start
配置,选择您的设备,然后点击旁边的绿色三角形(运行)按钮:
您应在设备上看到应用:
我们尚未添加任何代码来跟踪睡眠,后续部分将详细介绍这一操作。
在下一部分中,我们将了解所需的库和权限。
3. 查看库并添加权限
查看 build.gradle 和 AndroidManifest.xml
如需在应用中使用 Sleep API,您必须在应用清单中声明依赖 Google Location and Activity Recognition API 并指定 com.google.android.gms.permission.ACTIVITY_RECOGNITION
权限。
- 在
start
模块的build.gradle
文件中,搜索 TODO: Review play services library required for activity recognition。此步骤无需采取任何操作。只需查看我们要求声明的依赖项即可。代码应如下所示:
// TODO: Review play services library required for activity recognition.
implementation 'com.google.android.gms:play-services-location:18.0.0'
- 在
start
模块的AndroidManifest.xml
中,搜索 TODO: Add activity recognition and boot complete permissions,并将以下代码添加到<manifest>
元素中。
<!-- TODO: Add activity recognition and receive boot complete permissions. -->
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
现在,您的代码应如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.example.sleepcodelab">
...
<!-- TODO: Add activity recognition and receive boot complete permissions. -->
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
</manifest>
从注解中可以看出,您需要针对 API 版本 29 添加运行时权限。
大功告成!您的应用现在支持睡眠运动状态识别功能。我们只需添加此代码即可获得此功能。
查看运动状态识别权限检查
我们需要根据需要检查并请求运行时权限:
- 在
MainActivity.kt
中,我们将检查运动状态识别权限。 - 如果未授予权限,我们将调用
displayPermissionSettingsSnackBar()
。该信息条将显示相应权限需求,并允许用户在系统设置中批准权限。
在 start
模块的 MainActivity.kt
中,搜索 TODO: Review Activity Recognition permission check。您应该会看到以下代码段。
请注意,这一部分无需采取任何操作。
// TODO: Review Activity Recognition permission checking.
private fun activityRecognitionPermissionApproved(): Boolean {
return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACTIVITY_RECOGNITION
);
}
启用/停用睡眠跟踪功能
在 start
模块的 MainActivity.kt
中,搜索 TODO: Enable/Disable Sleep tracking and ask for permissions if needed。将 onClickRequestSleepData()
方法替换为以下代码。
// TODO: Enable/Disable sleep tracking and ask for permissions if needed.
fun onClickRequestSleepData(view: View) {
if (activityRecognitionPermissionApproved()) {
if (subscribedToSleepData) {
unsubscribeToSleepSegmentUpdates(applicationContext, sleepPendingIntent)
} else {
subscribeToSleepSegmentUpdates(applicationContext, sleepPendingIntent)
}
} else {
requestPermissionLauncher.launch(permission.ACTIVITY_RECOGNITION)
}
}
如果运动状态识别权限请求获得批准,并且用户订阅了睡眠数据,我们就会订阅睡眠更新。否则,我们会退订。
如果该权限请求未获批准,我们会将用户转到启动画面 activity,其中解释了我们为何需要该权限并允许他们启用该权限。
4. 订阅 Sleep API 更新
创建 PendingIntent
在 start
模块的 MainActivity.kt
中,搜索 TODO: Create a PendingIntent for Sleep API events。将其替换为以下代码段。
// TODO: Create a PendingIntent for Sleep API events
sleepPendingIntent =
SleepReceiver.createSleepReceiverPendingIntent(context = applicationContext)
现在,我们可以在 Sleep API 数据可用时获取更新。
请求 Sleep API 更新
在 start
模块的 MainActivity.kt
中,搜索 TODO: Request Sleep API updates。将其替换为以下代码段。
// TODO: Request Sleep API updates
val task = ActivityRecognition.getClient(context).requestSleepSegmentUpdates(
pendingIntent,
// Registers for both SleepSegmentEvent and SleepClassifyEvent data.
SleepSegmentRequest.getDefaultSleepSegmentRequest()
)
task.addOnSuccessListener {
mainViewModel.updateSubscribedToSleepData(true)
Log.d(TAG, "Successfully subscribed to sleep data.")
}
task.addOnFailureListener { exception ->
Log.d(TAG, "Exception when subscribing to sleep data: $exception")
}
成功注册 Sleep API 更新后,您的应用将在已注册的 PendingIntent 中接收睡眠检测通知。
启动完成后重新订阅
在 start
模块的 receiver/BootReceiver.kt
中,搜索 TODO: Request Sleep API on boot complete。将其替换为以下代码段。
// TODO: Request Sleep API upon boot complete
val subscribedToSleepData = repository.subscribedToSleepDataFlow.first()
if (subscribedToSleepData) {
subscribeToSleepSegmentUpdates(
context = context,
pendingIntent = SleepReceiver.createSleepReceiverPendingIntent(context)
)
}
上述代码可让应用在设备重新启动后继续接收 Sleep API 更新。
5. 处理事件
当发生睡眠分类或睡眠时间检测事件时,您的应用会收到一个 Intent 回调。您可以从此 intent 中提取一系列 SleepSegmentEvent 或 SleepClassifyEvent 对象。
我们来添加处理这些事件的代码。
在 start
模块的 receiver/SleepReceiver.kt
中,搜索 TODO: Extract sleep information from PendingIntent。在注解之后添加以下代码。
// TODO: Extract sleep information from PendingIntent.
if (SleepSegmentEvent.hasEvents(intent)) {
val sleepSegmentEvents: List<SleepSegmentEvent> =
SleepSegmentEvent.extractEvents(intent)
addSleepSegmentEventsToDatabase(repository, sleepSegmentEvents)
} else if (SleepClassifyEvent.hasEvents(intent)) {
val sleepClassifyEvents: List<SleepClassifyEvent> =
SleepClassifyEvent.extractEvents(intent)
addSleepClassifyEventsToDatabase(repository, sleepClassifyEvents)
}
此操作会将 SleepSegmentEvent
或 SleepClassifyEvent
数据保存到 Room 数据库中。MainActivity 使用 LiveData 通过 ViewModel 访问该数据库信息。如需详细了解这些类如何协同运行,请参阅Codelab 课程“带 View 的 Room”。
大功告成,此步骤已完成!请尝试运行应用。
6. 安装应用并查看代码
使用数据线将您的设备连接到工作站。点击 Android Studio 中的“Run”,即可在您的设备上安装并运行应用。授予运动状态识别权限并点按“SUBSCRIBE TO SLEEP DATA”按钮后,第一个 SleeveClassificationEvent 会在大约 10 分钟后显示。SleepSegmentEvent 应该会在一天内显示。
您随时可以浏览完整代码,查看您所完成的工作,并更好地了解代码如何协同运行。
选择性查看代码
您可以选择性查看以下代码。它们提供有关 Sleep API 和数据库实体之间数据映射的详细信息:
data/db/SleepClassifyEventEntity.kt
data/db/SleepSegmentEventEntity.kt