Introduction to Android Slices - Part I

Android Slices are a brand new way to display remote content from your application in many different places, such as Google Search (and Google Assistant in the future).
We can think of them as interactive, templated views. Thanks to standardized rules how Slices can be created, they can be used across many different Android versions. Slices are part of Android Jetpack, which makes them backwards compatible back to API 19 (KitKat) - so Slices will be available almost to all users of Android devices.
Why should I use them?
- Navigation
The first major advantage of using Slices is navigation to your app. Whenever a user starts to search something your application is able to display content created by you. For example, imagine creating a complex weather application. How cool will it be if you can display current weather in user’s location just after he finishes typing ‘weather’ in Google Search? With Android Slices user doesn’t have to launch your app to use it - your app content will be presented to the user as one of the search results. What is more, the user can jump right to your application just by tapping on the search result.
- Actions
Interactive actions are the next major feature of Android Slices. Thanks to it, a user can take action immediately in your app just by clicking on Slice. Imagine a bank application which has a blocking credit card feature. The user knows it can be done, but first, launching the app and navigating to proper screen needs to be performed in order to block credit card. With Android Slices, the only thing user needs to do is just to type “card” in Google Search - one of the results will be “Block Card”. Of course, after clicking on it, proper action will be executed right in your application.
- Discovery
You can use Slices to deliver your content when a
What do I need to create my Slices?
To be able to implement your own Slice you will need:
- Application migrated to AndroidX (though it is missing in official documentation)
- Android Studio 3.2 (in case you need to migrate to AndroidX or to be able to create SliceProvider from the template)
- Installed SliceViewer application on your device/emulator
Our first Slice
The first thing we need to do is create SliceProvider which will be responsible for delivering our Slices to other applications. We can create it from the template (if we are using Android Studio 3.2+) by right-clicking on the application package and choosing New -> Other -> SliceProvider. IDE will create all the boilerplate code for us including Gradle dependencies and modifying AndroidManifest.xml file.
Tip: If you are using Kotlin, its worth to use slice-builders-ktx
As you see, the whole process has generated many lines of code. For now, we don’t need to go through all of the methods - we are interested only in one of them.
onBindSlice(Uri) is the most important method of SliceProvider. Its responsible for creating Slice from desired URI. If some application
override fun onBindSlice(sliceUri: Uri): Slice? {
val context = context ?: return null
return if (sliceUri.path == "/hello-world") {
list(context, sliceUri, ListBuilder.INFINITY) {
row {
title = "Hello world!"
primaryAction = createActivityAction()
}
}
} else null
}
That wasn’t hard - we created our first Slice very easily. But what we should do to be able to see our work? We need an application which can display Slices.
Testing Slices
As I mentioned before, we will need to install the SliceViewer application. You can obtain it here. Download and install it on your emulator or real device
adb shell am start -a android.intent.action.VIEW -d slice-<uri>
Where URI is for example: content://com.example.slices/hello-world
It is a standard command for starting intent with data. After executing it, SliceViewer should launch and present your slice for you:
More than ‘Hello World’
Of course, simple Hello World is not all you can do with Slices. Basically, we can divide them into three categories:
- Basic Slices
That's the easiest and less complex Slice type. It’s used to present some kind of static data, as we have done it in ’Our first Slice’ paragraph. It can contain more data, rows or images but those are always static and its purpose is to present content for a user and redirect him to your app.
- Interactive Slices
This kind of slices is made for handling user input. We define actions which will be executed by our application. We can use built-in support for sliders and toggles to create engaging actions our user can perform.
- Dynamic Slices
We are using dynamic slices for displaying content highly bounded with our application. This kind of slices can fetch data from the application, modify app content or perform rich in-app actions.
Building more advanced Slices
As I said before, Slices are templated. That means we can use only predefined builders and not our custom views. The root of every Slice is ListBuilder, and as you remember we used it in our first Slice. We can add to it various types of items like rows, headers, actions and input widgets. It gives us the opportunity to create rich and complex Slices using very clean API. Our ListBuilder can contain:
- Actions
- Header
- Row
- Grid
- Range item
- Range input item
- See more action
For detailed information about how to use those components, you can visit official Android documentation where each element is explained. Below you can see the code which combines some types of supported builders:
return list(context, uri, ListBuilder.INFINITY) {
row {
title = "Warsaw"
subtitle = "19°C, Sunny"
primaryAction = createGenericAction(R.drawable.ic_wb_sunny_black_24dp, "Open App Action")
setTitleItem(
IconCompat.createWithResource(context, R.drawable.ic_wb_sunny_black_24dp).apply {
setTint(Color.parseColor("#F8F523"))
}, ListBuilder.SMALL_IMAGE
)
}
gridRow {
cell {
addImage(IconCompat.createWithResource(context, R.drawable.ic_wb_cloudy_black_24dp), ListBuilder.SMALL_IMAGE)
addTitleText("Monday")
addText("15°C, Cloudy")
}
cell {
addImage(IconCompat.createWithResource(context, R.drawable.ic_wb_sunny_black_24dp), ListBuilder.SMALL_IMAGE)
addTitleText("Tuesday")
addText("16°C, Sunny")
}
cell {
addImage(IconCompat.createWithResource(context, R.drawable.ic_wb_cloudy_black_24dp), ListBuilder.SMALL_IMAGE)
addTitleText("Wednesday")
addText("18°C, Cloudy")
}
}
setSeeMoreAction(PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0))
}
}
Here is how our Slice looks like:
Supporting different Slice sizes
Slices can be presented in three sizes. How they will be displayed depends on how much space is left on the screen. To be sure our Slice will be displayed properly we should test it across different Slice modes and know how they behave:
- Small
They are restricted by height, so only first of our rows will be displayed with all actions and content in it.
- Large
Large Slices will contain all the rows you created if scrolling is enabled or as many items as it can fit.
- Shortcut
When our Slice is presented as a shortcut only our first row (or header) primary action will be displayed as an icon.
Thanks to SliceViewer we can easily test if our Slice is displayed properly in each mode - we have to change mode in SliceViewer application toolbar:
Let's see how our previous example will look in those modes:
- Small
- Large
- Shortcut
Now we can be sure our Slices will be displayed properly on any kind of Android device!
Final Words
Please remember that SliceBuilders API for Kotlin (slice-builders-
In next part of our Android Slices Introduction we will take a closer look on the building Interactive and Dynamic Slices. Stay tuned!
If you want to see the whole code used in this article, check out this GitHub repository:
https://github.com/GabrielSamojlo/android-slices/tree/introduction
Happy coding!