Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to develop Slices apps

How to develop Slices apps

More Decks by Daichi Furiya (Wasabeef)

Other Decks in Programming

Transcript

  1. Gradle buildscript { repositories { google() } dependencies { classpath

    'com.android.tools.build:gradle:3.2.0-alpha15' } } // ... dependencies { implementation 'androidx.slice:slice-core:1.0.0-alpha1' implementation ‘androidx.slice:slice-builders:1.0.0-alpha1' // ssIf you wanna use SliceView implementation 'androidx.slice:slice-view:1.0.0-alpha1' }
  2. AndroidManifest.xml <application ... <provider android:name=".MySliceProvider" android:authorities="jp.wasabeef.slices" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW"

    /> <category android:name="android.app.slice.category.SLICE" /> </intent-filter> </provider> <activity android:name=".MainActivity"> ... </activity> </application>
  3. AndroidManifest.xml <application ... <provider android:name=".MySliceProvider" android:authorities="jp.wasabeef.slices" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW"

    /> <category android:name="android.app.slice.category.SLICE" /> </intent-filter> </provider> <activity android:name=".MainActivity"> ... </activity> </application>
  4. AndroidManifest.xml <application ... <provider android:name=".MySliceProvider" android:authorities="jp.wasabeef.slices" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW"

    /> <category android:name="android.app.slice.category.SLICE" /> </intent-filter> </provider> <activity android:name=".MainActivity"> ... </activity> </application>
  5. AndroidManifest.xml <application ... <provider android:name=".MySliceProvider" android:authorities="jp.wasabeef.slices" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW"

    /> <category android:name="android.app.slice.category.SLICE" /> </intent-filter> </provider> <activity android:name=".MainActivity"> ... </activity> </application>
  6. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  7. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  8. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  9. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { /** content://jp.wasabeef.slices/ping **/ } "/open" -> { /** content://jp.wasabeef.slices/open **/ } "/map" -> { /** content://jp.wasabeef.slices/map **/ } "/dog" -> { /** content://jp.wasabeef.slices/dog **/ } "/cat" -> { /** content://jp.wasabeef.slices/cat **/ } else -> null } } }
  10. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  11. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  12. SliceProvider class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  13. Basic Sample OK $ adb shell am start -a android.intent.action.VIEW

    \ -d slice-content://jp.wasabeef.slices/ping NG $ adb shell am start -a android.intent.action.VIEW \ -d slice-content://jp.wasabeef.slices/hoge
  14. SliceAction override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path)

    { "/open" -> createOpenActivity(sliceUri) else -> null } } private fun createOpenActivity(sliceUri: Uri): Slice { return ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.apply { setTitle("Perform action in app") setPrimaryAction(createActivityAction()) } }.build() } private fun createActivityAction(): SliceAction { val intent = Intent(context, MainActivity::class.java) return SliceAction(PendingIntent.getActivity(context, 0, intent, 0), IconCompat.createWithResource(context, R.mipmap.ic_launcher), "Open MainActivity.") }
  15. SliceAction override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path)

    { "/open" -> createOpenActivity(sliceUri) else -> null } } private fun createOpenActivity(sliceUri: Uri): Slice { return ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.apply { setTitle("Perform action in app") setPrimaryAction(createActivityAction()) } }.build() } private fun createActivityAction(): SliceAction { val intent = Intent(context, MainActivity::class.java) return SliceAction(PendingIntent.getActivity(context, 0, intent, 0), IconCompat.createWithResource(context, R.mipmap.ic_launcher), "Open MainActivity.") }
  16. SliceAction package androidx.slice.core; ... /** * Interface for a slice

    action, supports tappable icons, custom toggle icons, * and default toggles. */ public interface SliceAction { @Nullable SliceAction setContentDescription(@NonNull CharSequence description); SliceAction setChecked(boolean isChecked); SliceAction setPriority(@IntRange(from = 0) int priority); @Nullable PendingIntent getAction(); @Nullable IconCompat getIcon(); @Nullable CharSequence getTitle(); @Nullable CharSequence getContentDescription(); int getPriority(); boolean isToggle(); boolean isChecked(); @SliceHints.ImageMode int getImageMode(); boolean isDefaultToggle(); }
  17. SliceAction /** * Construct a SliceAction representing a tappable icon.

    * * @param action the pending intent to invoke for this action. * @param actionIcon the icon to display for this action. * @param actionTitle the title for this action, also used for content description * if one hasn't * been set via {@link #setContentDescription(CharSequence)}. */ public SliceAction(@NonNull PendingIntent action, @NonNull IconCompat actionIcon, @NonNull CharSequence actionTitle) { this(action, actionIcon, ICON_IMAGE, actionTitle); }
  18. Primary Action Sample http://www.meg-snow.com/products/ $ adb shell am start -a

    android.intent.action.VIEW \ -d slice-content://jp.wasabeef.slices/open
  19. GridRow class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } } http://www.meg-snow.com/products/
  20. GridRow class MySliceProvider : SliceProvider() { override fun onCreateSliceProvider(): Boolean

    = true override fun onBindSlice(sliceUri: Uri): Slice? { return when (sliceUri.path) { "/ping" -> { ListBuilder(context, sliceUri, INFINITY) .addRow { it.setTitle("pong") } .build() } else -> null } } }
  21. GridRow return ListBuilder(context, sliceUri, INFINITY) .addGridRow { it.apply { addCell

    { // title, image, intent …etc } addCell { // title, image, intent …etc } addCell { // title, image, intent …etc } } }.build() http://www.meg-snow.com/products/
  22. SliceView http://www.meg-snow.com/products/ http://www.meg-snow.com/products/ val sliceUri = Uri.parse("content://jp.wasabeef.slices/open") // Sync val

    manager = SliceManager.getInstance(context!!) sliceView.slice = manager.bindSlice(sliceUri) // Async and LiveData SliceLiveData.fromUri(context, sliceUri) .observe(this, Observer({ sliceResult -> sliceView.slice = sliceResult }))