The Nearby module in GMSCore provides a Slice at content://com.google.android.gms.nearby.sharing/scan. This allows your app to display live data of nearby Quick Share targets. Clicking a target in the slice opens the main Quick Share screen to begin the transfer.
Implementation Steps
- Derive the Slice URI:
content://com.google.android.gms.nearby.sharing/scan. - Get an instance of
SliceViewManager. - Register a callback using
registerSliceCallback to handle incoming Slice updates. - Crucial: Bind the slice using
bindSlice(sliceUri) after registering the callback to avoid race conditions.
When parsing the slice, look for items with LIST_ITEM and ACTIVITY hints. Target device names are found in items with the TEXT format and TITLE hint. Actions are found in items with SHORT_CUT and TITLE hints.
// Derive the Slice URI.
val sliceUri = Uri.parse("content://com.google.android.gms.nearby.sharing/scan")
// Get the SliceViewManager
val sliceManager = SliceViewManager.getInstance(context)
// Pin the slice and register your callback.
sliceManager.registerSliceCallback(sliceUri, { slice: Slice? ->
if (slice == null) {
return
}
for (targetItem in slice.items.reversed()) {
// Each row containing a target has the hints LIST_ITEM and ACTIVITY.
if (!(targetItem.format == SLICE && targetItem.hints.containsAll(listOf(LIST_ITEM, ACTIVITY)))) {
continue
}
val targetSlice = targetItem.slice
var deviceName: String? = null
var action: PendingIntent? = null
var profileIcon: IconCompat? = null
for (item in targetSlice.items) {
// The slice item of the target's device name contains the TITLE hint.
if (item.format == TEXT && item.hints.contains(TITLE)) {
deviceName = item.text.toString()
}
// The slice item of the target action contains the SHORTCUT and TITLE hints.
if (item.format == ACTION && item.hints.containsAll(listOf(SHORTCUT, TITLE))) {
action = item.action
val iconSlice: Slice? = item.slice
if (iconSlice != null) {
for (iconitem in iconSlice.items) {
// The target's icon is indicated by the IMAGE slice item format and the NO_TINT hint.
if (iconitem.format == IMAGE && iconitem.hints.contains(NO_TINT)) {
profileIcon = iconitem.icon
}
}
}
}
}
// Returns null if the data parsed from the slice is incomplete.
if (deviceName == null || action == null || profileIcon == null) {
continue
}
}
})
// Remember to bind the slice after you pin it to avoid race conditions!
val slice = sliceManager.bindSlice(sliceUri)