[Anton Minashkin] Android Slices: Searchify your app

[Anton Minashkin] Android Slices: Searchify your app

Presentation from GDG DevFest Ukraine 2018 - the biggest community-driven Google tech conference in the CEE.

Learn more at: https://devfest.gdg.org.ua

__

Slices is the new API introduced as part of Android P (and a Jetpack). The main aim of it is to provide yet another way for app to present it content remotely. Lets discuss how we can use it to build interactive Google Search results on Android and make better integration with Google Assistant.

3a6de6bc902de7f75c0e753b3202ed52?s=128

Google Developers Group Lviv

October 12, 2018
Tweet

Transcript

  1. Android Slices: Searchify your app by Anton Minashkin

  2. #dfua Slices Slices are UI templates that can display rich,

    dynamic, and interactive content.
  3. #dfua Slices

  4. #dfua Slices Support for Slices is built into Android Jetpack

    and can extend all the way back to Android 4.4
  5. #dfua Example

  6. #dfua Example

  7. #dfua Example <provider android:name=".MySliceProvider" android:authorities="com.example.anton_minashkin.archtest" android:exported="true"> ... </provider>

  8. #dfua Example <provider ...> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.app.slice.category.SLICE"

    /> ... </intent-filter> </provider>
  9. #dfua Example <provider ...> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.app.slice.category.SLICE"

    /> ... </intent-filter> </provider>
  10. #dfua Example <provider...> <intent-filter> ... <data android:host="example.com" android:pathPrefix="/" android:scheme="http" />

    </intent-filter> </provider>
  11. #dfua Example class MySliceProvider : SliceProvider() { override fun onMapIntentToUri(intent:

    Intent?): Uri {...} override fun onBindSlice(sliceUri: Uri): Slice? {...} private fun createActivityAction(): SliceAction? {...} override fun onSlicePinned(sliceUri: Uri?) {...} override fun onSliceUnpinned(sliceUri: Uri?) {...} }
  12. #dfua Example class MySliceProvider : SliceProvider() { override fun onMapIntentToUri(intent:

    Intent?): Uri {...} override fun onBindSlice(sliceUri: Uri): Slice? {...} private fun createActivityAction(): SliceAction? {...} override fun onSlicePinned(sliceUri: Uri?) {...} override fun onSliceUnpinned(sliceUri: Uri?) {...} }
  13. #dfua Example class MySliceProvider : SliceProvider() { override fun onMapIntentToUri(intent:

    Intent?): Uri {...} override fun onBindSlice(sliceUri: Uri): Slice? {...} private fun createActivityAction(): SliceAction? {...} override fun onSlicePinned(sliceUri: Uri?) {...} override fun onSliceUnpinned(sliceUri: Uri?) {...} }
  14. #dfua Example class MySliceProvider : SliceProvider() { override fun onMapIntentToUri(intent:

    Intent?): Uri {...} override fun onBindSlice(sliceUri: Uri): Slice? {...} private fun createActivityAction(): SliceAction? {...} override fun onSlicePinned(sliceUri: Uri?) {...} override fun onSliceUnpinned(sliceUri: Uri?) {...} }
  15. #dfua Example class MySliceProvider : SliceProvider() { override fun onMapIntentToUri(intent:

    Intent?): Uri {...} override fun onBindSlice(sliceUri: Uri): Slice? {...} private fun createActivityAction(): SliceAction? {...} override fun onSlicePinned(sliceUri: Uri?) {...} override fun onSliceUnpinned(sliceUri: Uri?) {...} }
  16. #dfua Example class MySliceProvider : SliceProvider() { override fun onMapIntentToUri(intent:

    Intent?): Uri {...} override fun onBindSlice(sliceUri: Uri): Slice? {...} private fun createActivityAction(): SliceAction? {...} override fun onSlicePinned(sliceUri: Uri?) {...} override fun onSliceUnpinned(sliceUri: Uri?) {...} }
  17. #dfua onBindSlice override fun onBindSlice(sliceUri: Uri): Slice? { val activityAction

    = createActivityAction() return if (sliceUri.path == "/hello") { list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction = activityAction title = "Hello World." } } } else {...} }
  18. #dfua onBindSlice override fun onBindSlice(sliceUri: Uri): Slice? { val activityAction

    = createActivityAction() return if (sliceUri.path == "/hello") { list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction = activityAction title = "Hello World." } } } else {...} }
  19. #dfua onBindSlice list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction =

    activityAction title = "Hello World." } }
  20. #dfua onBindSlice list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction =

    activityAction title = "Hello World." } }
  21. #dfua onBindSlice list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction =

    activityAction title = "Hello World." } }
  22. #dfua onBindSlice list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction =

    activityAction title = "Hello World." } }
  23. #dfua onBindSlice list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction =

    activityAction title = "Hello World." } }
  24. #dfua onBindSlice

  25. #dfua Dynamic Slices

  26. #dfua Dynamic Slices list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction

    = toastAndIncrementAction title = "Count: ${MyBroadcastReceiver.receivedCount}" subtitle = "Click me" } }
  27. #dfua Dynamic Slices list(context, sliceUri, ListBuilder.INFINITY) { row { primaryAction

    = toastAndIncrementAction title = "Count: ${MyBroadcastReceiver.receivedCount}" subtitle = "Click me" } }
  28. #dfua Dynamic Slices class MyBroadcastReceiver : BroadcastReceiver() { override fun

    onReceive(context: Context, intent: Intent) { ... } companion object { var receivedCount = 0 } }
  29. #dfua Dynamic Slices class MyBroadcastReceiver : BroadcastReceiver() { override fun

    onReceive(context: Context, intent: Intent) { ... } companion object { var receivedCount = 0 } }
  30. #dfua Dynamic Slices override fun onReceive(context: Context, intent: Intent) {

    if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) { Toast.makeText(...).show() receivedCount++; context.contentResolver.notifyChange(sliceUri, null) } }
  31. #dfua Dynamic Slices override fun onReceive(context: Context, intent: Intent) {

    if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) { Toast.makeText(...).show() receivedCount++; context.contentResolver.notifyChange(sliceUri, null) } }
  32. #dfua Dynamic Slices override fun onReceive(context: Context, intent: Intent) {

    if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) { Toast.makeText(...).show() receivedCount++; context.contentResolver.notifyChange(sliceUri, null) } }
  33. #dfua Dynamic Slices

  34. #dfua Templates

  35. #dfua Templates • ListBuilder + SliceAction • Everything is a

    Row (almost)
  36. #dfua SliceAction

  37. #dfua SliceAction A SliceAction contains a label along with a

    PendingIntent and is one of the following: • Icon button • Default toggle • Custom toggle (a drawable with an on/off state)
  38. #dfua SliceAction

  39. #dfua SliceAction TODO: 1. Main Action (click) 2. Toggle Action

    3. Template
  40. #dfua SliceAction TODO: 1. Main Action (click) 2. Toggle Action

    3. Template
  41. #dfua SliceAction val wifiAction = SliceAction.create( wifiSettingsPendingIntent, IconCompat.createWithResource(context, R.drawable.ic_wifi), ICON_IMAGE,

    "Wi-Fi Settings" )
  42. #dfua SliceAction val wifiAction = SliceAction.create( wifiSettingsPendingIntent, IconCompat.createWithResource(context, R.drawable.ic_wifi), ICON_IMAGE,

    "Wi-Fi Settings" )
  43. #dfua SliceAction val wifiAction = SliceAction.create( wifiSettingsPendingIntent, IconCompat.createWithResource(context, R.drawable.ic_wifi), ICON_IMAGE,

    "Wi-Fi Settings" )
  44. #dfua SliceAction val wifiAction = SliceAction.create( wifiSettingsPendingIntent, IconCompat.createWithResource(context, R.drawable.ic_wifi), ICON_IMAGE,

    "Wi-Fi Settings" )
  45. #dfua SliceAction TODO: 1. Main Action (click) 2. Toggle Action

    3. Template
  46. #dfua SliceAction val toggleAction = SliceAction.createToggle( wifiTogglePendingIntent, "Toggle Wi-Fi", isConnected

    /* isChecked */ )
  47. #dfua SliceAction val toggleAction = SliceAction.createToggle( wifiTogglePendingIntent, "Toggle Wi-Fi", isConnected

    /* isChecked */ )
  48. #dfua SliceAction val toggleAction = SliceAction.createToggle( wifiTogglePendingIntent, "Toggle Wi-Fi", isConnected

    /* isChecked */ )
  49. #dfua SliceAction val toggleAction = SliceAction.createToggle( wifiTogglePendingIntent, "Toggle Wi-Fi", isConnected

    /* isChecked */ )
  50. #dfua SliceAction TODO: 1. Main Action (click) 2. Toggle Action

    3. Template
  51. #dfua SliceAction return list(context, wifiUri, ListBuilder.INFINITY) { setAccentColor(0xff4285) // Specify

    color for tinting icons / controls. row { title = "Wi-Fi" primaryAction = wifiAction addEndItem(toggleAction) } }
  52. #dfua SliceAction return list(context, wifiUri, ListBuilder.INFINITY) { setAccentColor(0xff4285) // Specify

    color for tinting icons / controls. row { title = "Wi-Fi" primaryAction = wifiAction addEndItem(toggleAction) } }
  53. #dfua SliceAction return list(context, wifiUri, ListBuilder.INFINITY) { setAccentColor(0xff4285) // Specify

    color for tinting icons / controls. row { title = "Wi-Fi" primaryAction = wifiAction addEndItem(toggleAction) } }
  54. #dfua SliceAction return list(context, wifiUri, ListBuilder.INFINITY) { setAccentColor(0xff4285) // Specify

    color for tinting icons / controls. row { title = "Wi-Fi" primaryAction = wifiAction addEndItem(toggleAction) } }
  55. #dfua SliceAction

  56. #dfua DEMO

  57. Thank you! Questions? Vitaliy Zasadnyy DFUA Content Team