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 OOBE

As the final step of the OOBE, Fast Pair allows users to download the companion app for their headset, if desired. 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.

When launched by Fast Pair, the companion app will receive an intent with the following extra:

  • android.bluetooth.device.extra.DEVICE - the BluetoothDevice 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. After the user has finished the setup, the companion app should not provide this slice again.

@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);
}

After implementing the SliceProvider, you can input the provider's authority on the console. Alongside the authority, you'll also need to include the companion app's public signature SHA-256 digest (you can use apksigner to get the SHA-256 digest, instruction) so that Fast Pair can verify it is communicating with the correct app.

During certification, the above features will be tested and verified before approval.