1. 简介
观看上面的动画(持续活动演示)。注意:动画 GIF 仅播放一次。如果您错过了动画,请重新加载页面。
从表盘上,您会注意到会出现一个动画图标(用于计时器),如果用户点击它,它会启动为计时器提供支持的应用。
**持续活动**是 Wear OS 中的一项新功能,它允许**持续通知**出现在 Wear OS 用户界面内的其他界面上,从而使用户能够更专注于长时间运行的活动。
**持续通知**通常用于指示通知有一个后台任务,用户正在积极参与(例如,播放音乐)或以某种方式挂起,因此占用设备(例如,文件下载、同步操作或活动网络连接)。
例如,Wear OS 用户可以使用计时器应用来计时某个事件,然后导航离开该应用以开始其他任务(查看天气、开始锻炼等)。
当用户从计时器应用导航离开时,该应用通常会过渡到与某些后台工作(服务、闹钟管理器等)绑定的**持续通知**,以使用户了解计时器上还剩多少时间。
用户可以查看通知以获取更新,并且还可以与该通知进行交互。
但是,要查看通知,用户仍然需要滑动到表盘下方的通知栏并找到正确的通知,这不如其他界面方便。
使用**持续活动** API,应用可以将信息公开到 Wear OS 上多个新的、便捷的界面,以保持用户的参与度。
对于计时器应用,信息可以显示在用户的表盘上,作为可点击的图标(**屏幕截图底部的活动指示器**)
计时器应用还可以显示在全局应用启动器的“最近使用”部分,该部分列出了所有持续活动
全局启动器
最棒的是,您只需添加大约 10 行代码即可实现!
您将学到什么
- 创建和自定义**持续活动**
- 将**持续活动**绑定到**持续通知**
- 在设备/模拟器上测试**持续活动**
- 为您的**持续活动**添加交互(点击)
您将构建什么
您将扩展现有的步行追踪应用,并使用自定义**持续活动**在主表盘和应用启动器的“最近使用”部分显示活动步行的步行积分。
先决条件
- 了解Android 开发的基本知识
- 了解Kotlin 和协程的基本知识
2. 设置
在此步骤中,您将设置环境并下载入门项目。
您需要什么
- Android Studio
- Wear OS 模拟器(API 级别 >= 30)
- 持续活动仅在 API 级别 30 或更高版本上可用
- 模拟器新手?这里是如何设置的。
下载代码
如果您已安装 git,只需运行以下命令即可从此仓库克隆代码。要检查是否已安装 git,请在终端或命令行中键入git --version
并验证其是否正确执行。
git clone https://github.com/android/codelab-ongoing-activity.git cd ongoing-activity
如果您没有 git,您可以点击以下按钮下载此 codelab 的所有代码
您可以在 Android Studio 中随时运行任一模块,方法是更改工具栏中的运行配置。
在 Android Studio 中打开项目
- 在“欢迎使用 Android Studio”窗口中,选择打开
- 选择文件夹
[下载位置]
- 当 Android Studio 导入项目后,测试您是否可以在 Wear OS 模拟器或物理设备上运行
start
和finished
模块。 start
模块应如下面的屏幕截图所示。您将在其中进行所有工作。
通过开始步行锻炼来试用该应用。您应该注意到,您每隔约 3 秒就会开始获得积分。(该应用使用模拟数据,因此您无需实际四处走动。)
尝试从应用中滑动退出。如果您导航到表盘下方的导航栏,您应该能够找到继续跟踪步行积分的持续通知。
点击它如下所示
随时停止步行。
在本 codelab 结束时,相同的步行信息将显示在表盘和全局应用启动器的最近使用部分。
应用显示在表盘上(请参阅底部的活动指示器)
应用显示在应用启动器的最近使用部分
浏览开始代码
在start
模块中
build.gradle
包含基本的应用配置。它包含创建持续活动所需的依赖项。manifest > AndroidManifest.xml
包含将此标记为 Wear OS 应用的必要部分。java > ... > data > WalkingWorkoutsRepository.kt
链接到WalkingWorkoutsDataStore.kt
类以存储步行积分和步行锻炼的状态。不用担心细节,您无需在本 codelab 中查看这些类。java > ... > MainApplication.kt
创建存储库的单例。不用担心细节,您无需在本 codelab 中查看这些类。java > ... > ForegroundOnlyWalkingWorkoutService.kt
包含启动和停止步行锻炼的代码。如果锻炼处于活动状态并且用户从应用导航离开,它将从 Activity 中取消绑定并启动持续通知以使用户了解他们的锻炼积分(使用模拟数据)。我们将在此处添加我们的持续活动代码(在通知代码附近)。java > ... > MainActivity.kt
包含用于用户启动/停止步行锻炼的 UI。该活动绑定到上面的服务,以让该服务处理所有锻炼任务。java > ... > MainViewModel.kt
是一个简单的ViewModel
,用于处理MainActivity.kt
中的非 UI 代码。不用担心细节,您无需在本 codelab 中查看这些类。
3. 查看应用
该应用已成为一个功能完善的步行锻炼应用。
正如您在前面的步骤中看到的那样,您可以启动应用并启动/停止步行锻炼。在活动锻炼期间随着时间的推移,您将累积步行积分。
每次新的步行都会重置积分。
如果您在活动锻炼期间从应用导航离开,您可以向下滑动以查看一个**持续通知**,该通知会继续更新您的进度。
从该通知中,您可以停止通知中的锻炼或打开应用。
通常,您会使用专有算法从位置和传感器数据计算步行积分。在我们的例子中,我们只是模拟数据以简化操作。
它是如何工作的?
MainActivity
创建用户界面,链接到一个用于更新锻炼状态/步行积分的 ViewModel
,并绑定到一个服务。
当锻炼开始或停止时,MainActivity
会调用服务中的相应启动或停止方法来处理跟踪锻炼的繁重工作。
如果用户导航离开,MainActivity
则简单地从服务中解除绑定。
大部分“魔法”发生在 ForegroundOnlyWalkingWorkoutService
中。此类启动/停止锻炼并将任何状态或步行积分更改保存到存储库。
如果用户在会话期间从 MainActivity
导航离开,该服务还会转换为前台服务并将其绑定到一个**持续通知**。
**持续通知**继续跟踪锻炼的工作,并作为前台服务绑定到上述服务。
如果您不理解所有细节,请不要担心。重要的是要理解这是一个具有已构建通知的功能应用程序。我们只想扩展该通知,使其通过**持续活动**在更多表面上可见。
该通知代码位于 ForegroundOnlyWalkingWorkoutService
中,您将在本代码实验室中完成所有工作。
4. 创建持续活动
查看依赖项
在此步骤中,我们不会进行编码。相反,我们将审查持续活动依赖项。
在 start
模块中打开 app/build.gradle
文件,并搜索“TODO: Review dependencies for Ongoing Activity
”。
您应该看到以下内容
步骤 1
// TODO: Review dependencies for Ongoing Activity.
implementation libs.androidx.wear.ongoing
// Includes LocusIdCompat and new Notification categories for Ongoing Activity.
implementation libs.androidx.core.ktx
第一个依赖项是使用 Wear OS 持续活动 API 所必需的。
第二个依赖项是为了获取支持与持续活动结合使用的各种功能的最新通知 API 功能。以下两个功能可以应用于持续通知,因此也可以应用于持续活动
- 类别 - 当用户已启用勿扰模式时,Android 使用一些预定义的系统范围类别来确定是否应使用给定通知打扰用户。类别确定手表表盘上持续活动的优先级。最近添加了新类别以支持 Wear。
- LocusId - Locus 是 Android 10(API 级别 29)中引入的一个新概念,它允许 Android 系统关联不同子系统(例如内容捕获、快捷方式和通知)之间的状态。如果您有多个启动器,您可以使用 locus id 将您的持续活动绑定到特定的动态
快捷方式
,以便它在应用程序启动器的“最近使用”部分中正确显示。
查看持续通知代码
在此步骤中,我们不会进行任何编码。相反,我们只会查看通知代码。
在 start
模块中打开 ForegroundOnlyWalkingWorkoutService.kt
文件,并搜索“TODO: Review Notification builder code
”。
您应该看到以下内容
步骤 2
// TODO: Review Notification builder code.
val notificationBuilder = notificationCompatBuilder
.setStyle(bigTextStyle)
.setContentTitle(titleText)
.setContentText(mainText)
.setSmallIcon(R.mipmap.ic_launcher)
.setDefaults(NotificationCompat.DEFAULT_ALL)
// Makes Notification an Ongoing Notification (a Notification with a background task).
.setOngoing(true)
// Android uses some pre-defined system-wide categories to determine whether to
// disturb the user with a given notification when the user has enabled Do Not Disturb
// mode. The Category determines the priority of the Ongoing Activity and new
// categories were added recently to support Wear
.setCategory(NotificationCompat.CATEGORY_WORKOUT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.addAction(
R.drawable.ic_walk, getString(R.string.launch_activity),
activityPendingIntent
)
.addAction(
R.drawable.ic_cancel,
getString(R.string.stop_walking_workout_notification_text),
servicePendingIntent
)
// TODO: Create an Ongoing Activity.
// SKIP TODO FOR REVIEW STEP
return notificationBuilder.build()
查看上面的代码并阅读注释(跳过后面的 TODO 部分,那是以后步骤的内容)。
在此代码块上方还有更多通知代码,用于为构建器设置所有内容。
但是,对于本代码实验室,我们只需要关注通知构建器中的 setOngoing()
调用和 setCategory()
。
类别帮助 Wear OS 确定通知在手表表盘上的优先级。
setOngoing()
调用使我们的通知成为持续通知,即用户正在积极参与的具有后台任务的通知,例如跟踪步行锻炼。
当用户进行活跃的步行锻炼并从 MainActivity
导航离开时,我们会创建此通知。
创建持续活动
**持续活动**必须绑定到**持续通知**。我们有我们的持续通知,现在让我们创建一个持续活动。
搜索“TODO: Create an Ongoing Activity
”,并将“// SKIP TODO FOR REVIEW STEP
”行替换为以下代码。
步骤 4
// TODO: Create an Ongoing Activity.
val ongoingActivityStatus = Status.Builder()
// Sets the text used across various surfaces.
.addTemplate(mainText)
.build()
val ongoingActivity =
OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder)
// Sets icon that will appear on the watch face in active mode. If it isn't set,
// the watch face will use the static icon in active mode.
.setAnimatedIcon(R.drawable.animated_walk)
// Sets the icon that will appear on the watch face in ambient mode.
// Falls back to Notification's smallIcon if not set. If neither is set,
// an Exception is thrown.
.setStaticIcon(R.drawable.ic_walk)
// Sets the tap/touch event, so users can re-enter your app from the
// other surfaces.
// Falls back to Notification's contentIntent if not set. If neither is set,
// an Exception is thrown.
.setTouchIntent(activityPendingIntent)
// In our case, sets the text used for the Ongoing Activity (more options are
// available for timers and stop watches).
.setStatus(ongoingActivityStatus)
.build()
// Applies any Ongoing Activity updates to the notification builder.
// This method should always be called right before you build your notification,
// since an Ongoing Activity doesn't hold references to the context.
ongoingActivity.apply(applicationContext)
在创建持续活动之前,首先创建一个持续活动Status
,其中包含将在各种 Wear OS 表面上显示的文本。
我们使用 .addTemplate()
在 Status.Builder
上设置文本,使其与通知使用的主要文本相同。
您实际上可以自定义文本的显示方式(指定颜色、粗体等),但为了本代码实验室,我们将文本保持简单。但是,如果您想了解更多信息,请阅读持续活动指南。
接下来,我们创建 OngoingActivity
本身。我们将上下文、通知 ID 和我们在上面创建的通知构建器传递到 OngoingActivity.Builder()
的构造函数中。
通知 ID 和 NotificationCompat.Builder 实例对于将 OngoingActivity
绑定到持续通知非常重要。
首先,我们设置一个动画图标(用于活动模式下的手表表盘)和一个静态图标(用于环境模式下的手表表盘)。
接下来,我们设置一个触摸事件,最后使用前面创建的 Status
对象设置文本,然后使用 .build()
关闭语句。
OngoingActivity
用户界面使用图标和 Status
的文本提供。触摸事件允许用户从手表表盘或全局应用程序启动器的“最近使用”部分点击返回应用程序。
最后,我们在持续活动上调用 apply()
并传递上下文。这是将持续活动中的任何更改应用于通知构建器的最后一步。
就是这样,我们完成了!
当使用此通知调用 notificationManager.notify(NOTIFICATION_ID, notification)
时,它现在将显示在新的表面上!
现在,在新的 Wear OS 模拟器或设备上运行您的应用程序。
从应用程序开始步行,然后滑动退出应用程序。
在手表表盘上,您现在应该会看到一个小步行人图标,如下所示(但它是动画的)
如果您点击该图标,您将返回到应用程序!
再次退出应用程序,然后点击 Wear OS 设备上的应用程序启动器按钮。
您应该会看到类似以下内容
如果您点击“最近使用”部分中的步行应用程序,您应该再次进入应用程序!
5. 恭喜
恭喜!您学习了如何在 Wear OS 上构建持续活动!
持续活动是在 Wear 上在新的表面上吸引用户参与的一种好方法。
下一步是什么?
查看其他 Wear OS 代码实验室