1. 简介
观看上面的动画(持续性活动演示)。注意:GIF 动画只会播放一次。如果您没看到动画,请重新加载页面。
在表盘中,您会看到一个动画图标(代表计时器),如果用户点按该图标,系统会启动支持计时器的应用。
持续性活动是 Wear OS 中的一项新功能,可以让持续性通知显示于 Wear OS 界面内的其他 surface 中,从而提高用户与长时间进行的活动之间的互动度。
持续性通知通常用于表示该通知存在用户正与之积极互动的后台任务(例如,播放音乐),或者存在正等待进行某种处理并因此占用设备的后台任务(例如,文件下载、同步操作或活跃的网络连接)。
举个例子,某 Wear OS 用户可能使用计时器应用为某个事件计时,然后离开该应用并启动一些其他任务(查看天气、开始锻炼等)。
当用户离开计时器应用时,该应用通常会转换为与某些后台工作(服务、闹钟管理器等)相关联的持续性通知,让用户知道计时器上还剩多少时间。
用户可以查看通知以了解最新的计时,也可以与该通知互动。
不过,若要查看通知,用户仍然必须滑动到表盘下方的通知栏中,然后找到相应通知,这样的操作方式不如其他 surface 方便。
利用 Ongoing Activity API,应用就可以将信息显示于 Wear OS 中的多个新 surface 中,方便用户保持互动。
在计时器应用的例子中,信息可在用户的表盘上显示为可点按的图标(屏幕截图底部的活动指示器):
计时器应用还可以显示于全局应用启动器的“Recents”部分,该部分列出了所有持续性活动:
全局启动器
最重要的是,您只需添加 10 行左右的代码即可实现此功能!
学习内容
- 创建和自定义持续性活动
- 将持续性活动与持续性通知相关联
- 在设备/模拟器上测试持续性活动
- 为持续性活动添加互动(点按)
您将构建的内容
您将使用自定义的持续性活动扩展现有步行跟踪应用,持续性活动会在主表盘上和应用启动器的“Recents”部分显示正在进行的步行锻炼的分数。
前提条件
- 对 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 中打开项目
- 在“Welcome to Android Studio”窗口中,选择 Open
- 选择文件夹
[Download Location]
- Android Studio 导入项目后,请测试您能否在 Wear OS 模拟器或实体设备上运行
start
和finished
模块。 start
模块应如以下屏幕截图所示。您将在其中完成所有工作。
开始步行锻炼以试用该应用。您应该会发现,您开始每 3 秒左右获得分数。(该应用使用模拟数据,因此您不必真的四处走动。)
尝试滑动退出应用。如果您转到表盘下方的导航栏,应该能找到仍在继续跟踪步行分数的持续性通知。
点按后显示的内容如下所示:
您可以随时停止步行锻炼。
到此 Codelab 结束时,表盘和全局应用启动器的 Recents 部分将显示相同的步行信息。
应用显示于表盘上(请见底部的活动指示器):
应用显示于应用启动器的“Recents”部分:
探索起始代码
在 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
包含供用户开始/停止步行锻炼的界面。该 activity 与上述服务绑定,使其处理所有锻炼任务。java > ... > MainViewModel.kt
是一个简单的ViewModel
,用于处理MainActivity.kt
中的非界面代码。不用担心细节,在此 Codelab 中,您不需要查看这些类。
3. 查看应用
该应用已经是可以正常运行的步行锻炼应用。
正如您在前几步中看到的,您可以启动应用并开始/停止步行锻炼。在锻炼进行的过程中,您会持续累积步行分数。
每次开始新的步行锻炼,分数就会重置。
如果您在锻炼进行的过程中离开应用,向下滑动即可看到持续性通知,它会继续更新,让您掌握自己的进度。
在该通知中,您可以停止锻炼或打开应用。
通常,您会使用专有算法基于位置和传感器数据计算步行分数。在我们的例子中,为简单起见,我们只模拟数据。
运作方式
MainActivity
创建界面,链接到 ViewModel
以显示最新的锻炼状态/步行分数,并绑定到服务。
在锻炼开始或停止时,MainActivity
会调用服务中等效的开始或停止方法来处理繁重的锻炼跟踪工作。
如果用户离开,MainActivity
会直接与服务取消绑定。
大多数处理都发生在 ForegroundOnlyWalkingWorkoutService
中。正是该类负责开始/停止锻炼,并将任何状态更改或步行分数更改保存到代码库中。
如果用户在会话过程中离开 MainActivity
,服务还会转换为前台服务,并将自身关联到某个持续性通知。
持续性通知承担跟踪锻炼的工作并关联到上述服务(作为前台服务)。
如果您不了解所有细节,不用担心。重要的是明白这是一款可以正常运行的应用,并且已经构建了通知。我们只需要以持续性活动扩展该通知,使其可显示于更多 surface 上。
该通知的代码位于 ForegroundOnlyWalkingWorkoutService
中,您将在该类中完成此 Codelab 的所有工作。
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 Ongoing Activity API 所必需的。
第二个依赖项是为了获取通知 API 的最新功能,这些功能支持与持续性活动结合使用的各项功能。以下两个功能适用于持续性通知,因此也适用于持续性活动:
- 类别 - Android 使用一些预定义的系统范围类别来确定当用户启用了勿扰模式时,是否发出给定通知干扰客户。类别决定了持续性活动在表盘上的优先级。最近,新增了一些类别来支持 Wear。
- LocusId - Locus 是 Android 10(API 级别 29)中引入的新概念,可以让 Android 系统在内容捕获、快捷方式和通知等不同子系统之间关联状态。如果您有多个启动器,可以使用 Locus ID 将持续性活动绑定到特定的动态
Shortcut
,使其可正确显示于应用启动器的“Recents”部分。
查看持续性通知代码
在此步骤中,我们不会编写任何代码,而只会查看通知代码。
打开 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”部分,那是后续步骤的内容)。
此代码块上方还有许多通知代码,用于完成此构建器的所有设置。
不过,对于此 Codelab,我们只需要关注通知构建器中的 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 surface 上的文本。
我们使用 .addTemplate()
在 Status.Builder
上将文本设置为与用于通知的正文相同的文本。
实际上,您可以自定义文本的显示效果(指定颜色、粗体等),但我们在此 Codelab 中会使用简单的文本。不管怎样,如果您想了解详情,请参阅持续性活动指南。
接下来,我们创建 OngoingActivity
本身。将我们在此代码上方创建的上下文、通知 ID 和通知构建器传入 OngoingActivity.Builder()
的构造函数。
通知 ID 和 NotificationCompat.Builder 实例对于将 OngoingActivity
与持续性通知相关联非常重要。
首先,我们设置一个动画图标(针对处于活动模式的表盘)和一个静态图标(针对处于氛围模式的表盘)。
接下来,我们设置一个触摸事件,最后使用前面创建的 Status
对象设置文本,然后再使用 .build()
结束语句。
OngoingActivity
界面是使用该图标和 Status
的文本提供的。触摸事件让用户可以通过点按从表盘或全局应用启动器的“Recents”部分返回到应用中。
最后,我们对持续性活动调用 apply()
并传递上下文。这是将持续性活动的任何更改应用于通知构建器的最后一步。
好了,本课到此结束!
现在,以此通知调用 notificationManager.notify(NOTIFICATION_ID, notification)
时,它会显示于新 surface 上!
接下来,在新的 Wear OS 模拟器或设备上运行应用。
在应用中开始步行锻炼,然后滑动退出应用。
在表盘上,现在应该会显示一个如下所示的行走的小人图标(并非动画):
如果您点按此图标,就会返回到应用中!
再次退出应用,这一次点按 Wear OS 设备上的应用启动器按钮。
显示的内容应如下所示:
如果您点按“Recents”部分中的步行应用,应该会再次进入应用!
5. 恭喜
恭喜!您已了解如何在 Wear OS 中构建持续性活动!
持续性活动是在 Wear 中的新 surface 上与用户互动的有效方式。
后续操作
查看其他 Wear OS Codelab: