使用 Ongoing Activity API,以新方式吸引 Wear OS 用户

1. 简介

a3457956a1735674.gif

观看上面的动画(Ongoing Activity 演示)。注意:动画 GIF 只播放一次。如果您错过了动画,请重新加载页面。

在表盘上,您会注意到出现一个动画图标(用于计时器),如果用户点击它,就会启动运行计时器的应用。

Ongoing Activity 是 Wear OS 中的一项新功能,它允许 Ongoing Notification 出现在 Wear OS 用户界面的其他界面上,从而让用户能够更深入地参与到长时间运行的活动中。

Ongoing Notification 通常用于指示通知拥有用户正在积极参与的后台任务(例如,播放音乐),或者以某种方式处于待处理状态并因此占用设备(例如,文件下载、同步操作或活动的网络连接)。

例如,Wear OS 用户可以使用计时器应用来计时某个事件,然后离开该应用去启动其他任务(查看天气、开始锻炼等)。

当用户离开计时器应用时,该应用通常会转换为与某些后台工作(服务、闹钟管理器等)关联的 Ongoing Notification,以便让用户了解计时器还剩多少时间。

用户可以查看通知以获取更新,并且也可以与该通知进行交互。

但是,要查看通知,用户仍然需要向下轻扫进入表盘下方的通知栏并找到正确的通知,这不像其他界面那样方便。

借助 Ongoing Activity API,应用可以将信息呈现在 Wear OS 上多个新的便捷界面中,以便让用户保持参与。

以计时器应用为例,信息可以作为可点击图标显示在用户的表盘上(截屏底部的活动指示器

b65ade9bf43c526e.png

计时器应用还可以显示在全局应用启动器的最近使用部分,该部分列出了所有 Ongoing Activity

1bc84dd2bd2d2b5d.png

全局启动器

最棒的是,您只需添加大约 10 行代码即可实现!

您将学到什么

  • 创建和自定义 Ongoing Activity
  • Ongoing ActivityOngoing Notification 关联
  • 在设备/模拟器上测试 Ongoing Activity
  • 为您的 Ongoing Activity 添加交互(点击)

您将构建什么

您将扩展现有的步行追踪应用,使用自定义的 Ongoing Activity,在主表盘和应用启动器的最近使用部分显示当前步行的步行点数

前提条件

2. 设置环境

在此步骤中,您将设置环境并下载一个入门项目。

您需要准备什么

  • Android Studio
  • Wear OS 模拟器(API 级别 >= 30)
  • Ongoing Activity 仅在 API 级别 30 或更高版本上可用
  • 模拟器新手?此处介绍了如何设置。

下载代码

如果您已安装 git,只需运行以下命令即可从此仓库克隆代码。要检查是否已安装 git,请在终端或命令行中输入 git --version 并验证其是否正确执行。

git clone https://github.com/android/codelab-ongoing-activity.git
cd ongoing-activity

如果您没有安装 git,可以点击以下按钮下载此 Codelab 的所有代码

您可以在 Android Studio 中随时运行任一模块,方法是更改工具栏中的运行配置。

b059413b0cf9113a.png

在 Android Studio 中打开项目

  1. 在欢迎使用 Android Studio 窗口中,选择 Open
  2. 选择文件夹 [Download Location]
  3. 待 Android Studio 导入项目后,测试您能否在 Wear OS 模拟器或物理设备上运行 startfinished 模块。
  4. start 模块应如下面的屏幕截图所示。这是您将要进行所有工作的地方。

a40cc0c7e7e28bcf.png

通过开始步行锻炼来试用该应用。您应该注意到大约每 3 秒钟就会获得积分。(该应用使用模拟数据,所以您不必实际走动。)

尝试退出应用。如果您从表盘向下导航到导航栏,您应该能找到持续追踪您步行点数的 Ongoing Notification。

点击它看起来像这样

ac48b3ddc2a093bb.png

36fed11735ef4807.png

您可以随时停止步行。

完成此 Codelab 后,相同的步行信息将显示在表盘和全局应用启动器的最近使用部分。

应用显示在表盘上(请参阅底部的活动指示器

59747518d70b053a.png

应用显示在应用启动器最近使用部分

4817a55e6722629d.png

探索起始代码

start 模块中

  • build.gradle 包含基本应用配置。它包含创建 Ongoing Activity 所需的依赖项。
  • manifest > AndroidManifest.xml 包含将此标记为 Wear OS 应用的必要部分。
  • java > ... > data > WalkingWorkoutsRepository.kt 链接到 WalkingWorkoutsDataStore.kt 类,用于存储步行点数和步行锻炼状态。无需担心具体细节,您无需在此 Codelab 中查看这些类。
  • java > ... > MainApplication.kt 创建了仓库的单例。无需担心具体细节,您无需在此 Codelab 中查看这些类。
  • java > ... > ForegroundOnlyWalkingWorkoutService.kt 包含用于开始和停止步行锻炼的代码。如果锻炼处于活动状态且用户离开应用,它将解除与 Activity 的绑定,并启动 Ongoing Notification 以通知用户其锻炼点数(使用模拟数据)。这是我们将添加 Ongoing Activity 代码的地方(靠近通知代码)。
  • java > ... > MainActivity.kt 包含供用户开始/停止步行锻炼的 UI。此 activity 绑定到上面的服务,由服务处理所有锻炼任务。
  • java > ... > MainViewModel.kt 是一个简单的 ViewModel,用于处理 MainActivity.kt 中的非 UI 代码。无需担心具体细节,您无需在此 Codelab 中查看这些类。

3. 查看应用

该应用已经是一个功能完备的步行锻炼应用。

正如您在之前的步骤中所看到的,您可以启动应用并开始/停止步行锻炼。在锻炼期间随着时间的推移,您会累积步行点数

每次新步行都会重置点数。

如果在活动锻炼期间您离开应用,可以向下轻扫以查看持续更新您进度的 Ongoing Notification

您可以从该通知停止锻炼,或打开应用。

通常,您会使用专有算法从位置和传感器数据计算步行点数。在此,我们只是模拟数据以简化操作。

它是如何工作的?

MainActivity 创建用户界面,链接到 ViewModel 以获取锻炼状态/步行点数的更新,并绑定到一个服务。

当锻炼开始或停止时,MainActivity 会调用 Service 中相应的开始或停止方法来处理追踪锻炼的繁重工作。

如果用户离开,MainActivity 只需解除与服务的绑定。

大部分神奇之处都发生在 ForegroundOnlyWalkingWorkoutService 中。这个类负责开始/停止锻炼,并将状态或步行点数的任何更改保存到仓库中。

如果用户在会话期间离开 MainActivity,该服务还会转换为前台服务,并将其自身与 Ongoing Notification 关联。

Ongoing Notification 继续进行锻炼追踪工作,并作为前台服务与上面的服务关联。

如果您不理解所有细节,请不用担心。重要的是要理解这是一个功能完备的应用,并且其通知已经构建好了。我们只是想扩展该通知,使其借助 Ongoing Activity 在更多界面上可见。

该通知代码位于 ForegroundOnlyWalkingWorkoutService 中,这也是您在此 Codelab 中进行所有工作的地方。

4. 创建 Ongoing Activity

查看依赖项

在此步骤中,我们将不编写代码,而是查看 Ongoing Activity 的依赖项。

打开 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 需要第一个依赖项。

第二个依赖项是获取支持多种与 Ongoing Activity 结合使用的功能的 Notification API 的最新功能。以下两个功能可应用于 Ongoing Notification,因此也可应用于 Ongoing Activity

  • Category(类别) - Android 使用一些预定义的系统范围类别来确定在用户启用“请勿打扰”模式时是否向用户发出给定通知。Category 决定了 Ongoing Activity 在表盘上的优先级。最近添加了新类别来支持 Wear。
  • LocusId(位置 ID) - Locus 是 Android 10(API 级别 29)中引入的一个新概念,它允许 Android 系统关联不同子系统(例如内容捕获、快捷方式通知)之间的状态。如果您有多个启动器,可以使用 locus ID 将您的 Ongoing Activity 与特定的动态 Shortcut 关联,使其在应用启动器的最近使用部分正确显示。

查看 Ongoing Notification 代码

在此步骤中,我们将不编写任何代码,而是只查看通知代码。

打开 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()

Category 可帮助 Wear OS 确定表盘上通知的优先级。

setOngoing() 调用将我们的通知设为 Ongoing Notification,即用户正在积极参与的具有后台任务的通知,例如追踪步行锻炼。

当用户有活动的步行锻炼并离开 MainActivity 时,我们会创建此通知。

创建 Ongoing Activity

Ongoing Activity 必须与 Ongoing Notification 关联。我们已经有了 Ongoing Notification,现在来创建一个 Ongoing Activity。

搜索“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)

在创建 Ongoing Activity 之前,首先创建一个 Ongoing Activity Status,其中包含将显示在各种 Wear OS 界面上的文本。

我们在 Status.Builder 上使用 .addTemplate() 设置文本,与我们用于通知的主文本相同。

您实际上可以自定义文本的显示方式(指定颜色、加粗等),但为了本 Codelab 的简洁性,我们保持文本简单。但是,如果您想了解更多信息,请阅读Ongoing Activity 指南

接下来,我们创建 OngoingActivity 本身。我们将上下文、通知 ID 以及在此代码上方创建的通知构建器传递到 OngoingActivity.Builder() 的构造函数中。

通知 ID 和 NotificationCompat.Builder 实例非常重要,用于将 OngoingActivity 与 Ongoing Notification 关联。

首先,我们设置一个动画图标(用于活动模式下的表盘)和一个静态图标(用于微光模式下的表盘)。

接下来,我们设置一个触摸事件,最后使用我们之前创建的 Status 对象设置文本,最后用 .build() 结束语句。

OngoingActivity 用户界面通过图标和 Status 的文本提供。触摸事件允许用户从表盘或全局应用启动器的最近使用部分点击回到应用。

最后,我们在 Ongoing Activity 上调用 apply() 并传递上下文。这是将 Ongoing Activity 中的任何更改应用到通知构建器的最后一步。

就是这样,我们完成了!

当使用此通知调用 notificationManager.notify(NOTIFICATION_ID, notification) 时,它现在将出现在新的界面上!

现在在新 Wear OS 模拟器或设备上运行您的应用。

从应用开始步行并滑动退出应用。

在表盘上,您现在应该会看到一个小的步行者图标,如下图所示(但它是动态的)

59747518d70b053a.png

如果您点击该图标,您将回到应用中!

再次退出应用,现在点击您的 Wear OS 设备上的应用启动器按钮。

您应该会看到如下所示内容

4817a55e6722629d.png

如果您在最近使用部分点击步行应用,您应该会再次进入应用!

5. 恭喜

恭喜!您学会了如何在 Wear OS 上构建 Ongoing Activity!

Ongoing Activity 是在 Wear 中新的界面上吸引用户的绝佳方式。

下一步?

查看其他 Wear OS Codelab

进一步阅读