Fast Pair Companion App Integration

Fast Pair allows OEM companion apps to be deeply integrated into the pairing and usage experience. There are multiple integration points that can optionally be utilized to engage users after they've finished Fast Pairing.

Installation during the Out-Of-Box Experience (OOBE)

Fast Pair allows users to download the companion app for their headset as the final step of the Out-Of-Box Experience (OOBE). This is presented to the user in a notification telling them that pairing has finished and that they can either download the app if it isn't already installed, or else open the app and start using it.

To get started with this feature, add your companion app's package name to the device details on the console.

Companion apps launched by Fast Pair include an extra data element:

  • android.bluetooth.device.extra.DEVICE - the Bluetooth Device that triggered the notification.

Settings slice integration

Slices can be supplied by a companion app to the further enhance the options available on a device's Bluetooth settings page.

A SliceProvider must be implemented by a companion app to provide these settings slices. There are 2 types of slices available: an OOBE slice and generic settings items. The OOBE slice should be included if the user has not yet configured the headset within the companion app and the remaining slices should always be included, see the code sample below:

@Nullable
@Override
public Slice onBindSlice(Uri sliceUri) {
  String address = sliceUri.getQueryParameter("addr");
  if (address == null) {
    return null;
  }
  String path = sliceUri.getPathSegments().get(/* index= */ 0);
  if ("settings_slice".equals(path)) {
    return createSettingSlice(sliceUri, address);
  } else if ("oobe_slice".equals(path)) {
    return createOobeReminderSlice(sliceUri, address);
  }
  return null;
}

oobe_slice is used for reminding the users to finish setting up their device, if they haven't yet done so in the companion app. The companion app must not provide the slice again after user has completed device setup.

@Nullable
private Slice createOobeReminderSlice(Uri sliceUri, String address) {
  if (!deviceHasGoneThroughOobe(address)) {
    ListBuilder listBuilder =
        new ListBuilder(context, sliceUri, ListBuilder.INFINITY);
    addOobeSlice(listBuilder, context, address);
    return listBuilder.build();
  }
  return null;
}

private static void addOobeSlice(
    ListBuilder listBuilder, Context context, String address) {
  listBuilder.addRow(
      createRow(
          context,
          R.drawable.icon_oobe,
          R.string.title_oobe,
          R.string.summary_oobe,
          R.string.label_oobe,
          createOobePendingIntent(context, address)));
}

setting_slice is where companion apps can provide links to commonly used settings.

private Slice createSettingSlice(Uri sliceUri, String address) {
  ListBuilder listBuilder =
      new ListBuilder(context, sliceUri, ListBuilder.INFINITY);
  // TODO: Add your customized slice here.
  addRow1(listBuilder, context, address);
  addRow2(listBuilder, context, address);
  return listBuilder.build();
}

private static void addRow1(
    ListBuilder listBuilder, Context context, String address) {
  listBuilder.addRow(
      createRow(
          context,
          R.drawable.fp_slice_row1_icon,
          R.string.fp_slice_row1_title_gestures,
          R.string.fp_slice_row1_summary_gestures,
          R.string.fp_slice_row1_label_gestures,
          createPendingIntent(context, address)));
}

private static void addRow2(
    ListBuilder listBuilder, Context context, String address) {
  ...
}

Each Slice needs to have title, subtitle, icon and action.

private static RowBuilder createRow(
    Context context,
    @DrawableRes int iconId,
    @StringRes int titleId,
    @StringRes int summaryId,
    @StringRes int actionTitleId,
    PendingIntent pendingIntent) {
  SliceAction action =
      SliceAction.createDeeplink(
          pendingIntent,
          IconCompat.createWithResource(context, iconId),
          ListBuilder.ICON_IMAGE,
          context.getString(actionTitleId));
  return new RowBuilder()
      .setTitleItem(
          IconCompat.createWithResource(context, iconId),
          ListBuilder.ICON_IMAGE)
      .setTitle(context.getString(titleId))
      .setSubtitle(context.getString(summaryId))
      .setPrimaryAction(action);
}

Add the following to the console after implementing SliceProviderto allow the Fast Pair service to verify it is communicating with the correct app:

Firmware update Intent

When firmware version of a connected device is out of date, or precisely speaking different than the firmware version configured in the device console, Fast Pair will notify the companion app with a com.google.android.gms.nearby.fastpair.ACTION_FIRMWARE_UPDATE_BROADCAST Intent after a firmware version check. The Intent has the following extra information:

  • com.google.android.gms.nearby.fastpair.EXTRA_LOCAL_FIRMWARE_VERSION, the firmware version of the connected device
  • com.google.android.gms.nearby.fastpair.EXTRA_UPDATE_NOTIFICATION_SHOWN, set to true if Fast Pair has shown a notification