启用和自定义跨设备切换

“继续”功能引入了新的方法和类,供您指明对该功能的支持,并提供要传递的必要数据。这样,您就可以在接收设备上正确恢复用户体验。

启用支持

必须针对每项活动实现对“继续”功能(默认处于关闭状态)的支持。如需启用该功能,请调用 setHandoffEnabled,将当前 activity 表示为已准备好进行切换。调用 setHandoffEnabled(true, null) 后,activity 随时可能发生切换,因此请仅在 activity 准备好切换时调用它。

您可以使用 isHandoffEnabled 检查 activity 是否已启用“继续”。如果 activity 已启用切换,则还必须实现 onHandoffActivityDataRequested,以确保它返回非 null HandoffActivityData,因为未实现默认行为。

class MyHandoffActivity : Activity() {

    ...

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Do stuff
    ...
    // Enable handoff
    setHandoffEnabled(true, null)
  }

  // Override and implement onHandoffActivityDataRequested
  override fun onHandoffActivityDataRequested(handoffRequestInfo: HandoffActivityDataRequestInfo) : HandoffActivityData {
    // Create and return handoff data
  }
}

您可以使用任何相关 extra 和后备 URI 配置 HandoffActivityData 对象,以告知“继续”如何执行到接收设备的切换。

系统在以下两种情况下需要这些数据:

  • activity 即将进入后台,必须保存相关数据。
  • 该 activity 位于前台,并且已请求切换。您可以查看交接请求的状态。

查看状态

HandoffActivityDataRequestInfo 类提供有关当前切换 activity 请求的信息。使用 isActiveRequest 确定请求当前是否处于有效状态。如果该方法返回

  • true,则当前 activity 位于前台,并且用户已请求在其他设备上继续,但如果
  • false,该 activity 已停止且位于后台,但用户将来可能会请求切换。

在发送设备上,如果您想显示界面来向用户指示切换已发生或正在进行,可以检查 isActiveRequest 是否有活跃请求。不过,请勿在 onHandoffActivityDataRequested 中同步执行此代码。而是应将所有代码排入队列以异步运行,以免阻止或延迟切换。

// Override and implement onHandoffActivityDataRequested
override fun onHandoffActivityDataRequested(handoffRequestInfo: HandoffActivityDataRequestInfo) : HandoffActivityData {

  // Check whether the handoff request is active
  if (handoffRequestInfo.isActiveRequest()) {
    // Asynchronously show UI to let users know a handoff is in progress
  }

  // Create and return handoff data
}

创建切换数据

为确保在使用“继续”功能进行切换期间传递所有相关和必要的数据,您必须在 HandoffActivityData 对象中添加这些数据。

HandoffActivityData 类表示与 activity 关联的切换数据。HandoffActivityData 会告知“继续”功能如何在接收设备上处理和重新创建 activity。交接数据包括:

  • 组件名称(必需):要在接收设备上启动的相应 activity 的 ComponentName,以便在切换后继续用户的历程。在大多数情况下,为了精确复制 activity,这将是创建 HandoffActivityData 的同一 activity 的组件名称。
  • 其他(可选):您可以指定要包含在 activity 的启动 Intent 中的其他。这是一个 PersistableBundle,可用于向组件提供其他信息。Extra 必须小于 50KB。

如需创建 HandoffActivityData 对象,请使用构建器类 HandoffActivityData.Builder。通过传递应接收切换的 activity 的 ComponentName(例如,当前 Activity 的 this.getComponentName,或显式 ComponentName(this, TargetActivity::class.java))来构建新的构建器。然后,使用 setExtras 方法视需要指定 extra。最后,调用 build 以创建 HandoffActivityData 对象。

// Override and implement onHandoffActivityDataRequested
override fun onHandoffActivityDataRequested(handoffRequestInfo: HandoffActivityDataRequestInfo) : HandoffActivityData {

  // Check whether the handoff request is active
  if (handoffRequestInfo.isActiveRequest()) {
    // Asynchronously show UI to let users know a handoff is in progress
  }

  val extras: PersistableBundle = PersistableBundle()
  // Put relevant and necessary values into extras (e.g. scroll position)
  extras.putString("data_id", getDataId())
  extras.putInt("scroll_position", getScrollPosition())

  // Create and return handoff data
  return HandoffActivityData.Builder(getComponentName()) // Designate handoff to the same activity
    .setExtras(extras)
    .build()
}

设置网站后备选项

如果无法在接收设备上启动指定的 activity,您还可以使用 setFallbackUri 选择性地设置一个后备网址,以便在设备上通过用户的默认浏览器打开。

如需允许在未安装应用的接收设备上显示“继续”建议,请在调用 setHandoffEnabled 时传递 HandoffActivityParams 实例,并将 setAllowHandoffWithoutPackageInstalled 设置为 true:

setHandoffEnabled(
  true,
  HandoffActivityParams.Builder()
    .setAllowHandoffWithoutPackageInstalled(true)
    .build()
)

然后在 HandoffActivityData 中添加后备网址:

val fallbackWebLink: Uri = Uri.parse("https://myapp.com/fallback?query=" + paramVal)

val handoffData: HandoffActivityData = HandoffActivityData.Builder(getComponentName())
  .setExtras(extras)
  .setFallbackUri(fallbackWebLink)
  .build()

实现直接转到网站

或者,如需实现直接到网页的切换,请将 HandoffActivityParams 与 setAllowHandoffWithoutPackageInstalled(true) 一起传递给 setHandoffEnabled,并使用 HandoffActivityData.createWebHandoff 方法生成 HandoffActivityData:

val webHandoffLink: Uri = Uri.parse("https://myapp.com/handoff?query=" + paramVal)

val handoffData: HandoffActivityData = HandoffActivityData.createWebHandoff(webHandoffLink)

接收和处理交接 intent

在接收设备上,您的应用必须处理切换并重现发送设备上的用户体验。具体而言,在 onHandoffActivityDataRequested 返回的 HandoffActivityData 中指定的 activity 内,您需要处理 intent 并检索 extra,其中包含有关如何适当重新创建 activity 的信息。

如果您指定将切换到同一 Activity,则可以在该 Activity 的 onCreate 方法中接收 intent,以便检索数据并为用户适当预先填充数据。

class MyHandoffActivity : Activity() {

    ...

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Do stuff
    ...

    // Get the launch intent and retrieve extras
    val intent: Intent = getIntent()
    if (intent != null && intent.hasExtra("data_id")) {
      val dataID: String = intent.getStringExtra("data_id")
      // Retrieve the data that corresponds to the data ID
      ...
      // Populate activity UI with relevant data
      ...

      if (intent.hasExtra("scroll_position")) {
        val scrollPosition: Int = intent.getIntExtra("scroll_position", 0)
        // Move the page to the scroll position
        ...
      }
    }
  }
}