36

Code Your First Android Slice and Keep Users Engaged

 5 years ago
source link: https://www.tuicool.com/articles/hit/mYZZJv6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

The hard work isn’t over just because your app has racked up a ton of downloads and positive reviews on the Google Play store. Your typical mobile user has dozens of apps installed on their device, and with new apps being released all the time, you’ll need to work hard to hold your audience’s interest!

Keeping users coming back to your app is crucial to creating a stable, loyal user base. Plus, if you've monetized your app, then the amount of time people spend in your application directly affects how much money you make—think of every additional second as another opportunity to display an advert or tempt the user into splashing out on an in-app purchase!

At this year’s I/O, Google introduced slices , a new feature that promises to drive users back to your app by getting your app’s features and content in front of them at the exact moment when they're needed the most. 

With slices shaping up to be an important tool for retaining your audience, now’s the perfect time to get some hands-on experience with this up-and-coming Android feature. By the end of this article, you’ll have created a range of slices, from a simple slice that launches an Activity when tapped through to more complex slices consisting of icons, images, grids, and multiple SliceActions

Slices: More Ways for Users to Enjoy Your App

Similar to widgets, slices are snippets of content that appear outside of the application context, increasing your app’s visibility and providing you with more opportunities to engage your audience.

Slices have the potential to greatly increase your app’s visibility, with Google promising to add support for slices to the areas where many Android users spend significant amounts of time, including Google search and the Google Assistant. Since they're part of Android Jetpack, slices are compatible with Android 4.4 and higher, which means your slices have the potential to reach 95% of all Android users.

So slices have a lot to offer—but how do they work?

Currently, if you perform a search in the Google app then Google might suggest a relevant application that’s installed on your device. For example, if you’ve installed Facebook for Mobile, then typing facebook will bring up a direct link to the Facebook app.

YfAjiiy.png!web

Slices take this app linking one step further, by focusing on specific tasks the user might want to perform within the applications they’ve already installed.

Let’s look at an example: imagine you’ve installed a Book A Hotel app that lets you search for a hotel and reserve a room. When you type London hotels into Google, you encounter the usual search results, plus a slice from the Book A Hotel application. This slice recommends a hotel in London and displays information such as the hotel’s name and address, plus a SliceAction , in the form of a button that lets you reserve a room directly from the slice’s user interface (UI). 

For the user, this slice has provided easy access to the information and features they needed at that particular moment. For the developer, this slice has enabled them to get their application in front of a user at the exact point when they stood the greatest chance of successfully re-engaging them.

How Do I Create My First Slice?

Let’s start by creating a simple slice that, when tapped, will launch our application’s MainActivity .

This simple technique makes it possible to start any task, directly from a slice’s UI. In our Book A Hotel example, we could just link the button to the related app’s BookRoomActivity , which would be a simple but effective way to reduce the number of screens the user has to navigate in order to complete this particular task. 

To get started, create a new Android project. You can use whatever settings you want, but make sure you select the Include Kotlin support checkbox when prompted. 

Once you’ve created your project, open its build.gradle file and add the slice-core and slice-builder dependencies:

dependencies {
   implementation 'androidx.appcompat:appcompat:1.0.0-alpha3'
   implementation 'androidx.slice:slice-core:1.0.0-alpha3'
   implementation 'androidx.slice:slice-builders:1.0.0-alpha3'
   implementation 'androidx.constraintlayout:constraintlayout:1.1.0'
   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

Displaying Your App’s Content in Google Search, With Slice Providers

Next, we need to create a slice provider , which is the component responsible for displaying your app’s content outside of the application context. 

You create a slice provider by using Android Studio’s slice provider template:

  • Select New > Other > Slice Provider  from the Android Studio toolbar. 
  • Enter the name MySliceProvider .
  • Set the Source language to Kotlin .
  • Click Finish .
  • Open the MySliceProvider class, and you should see the following automatically generated code: 
import android.content.ContentResolver
import android.content.Intent
import android.net.Uri
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder

class MySliceProvider : SliceProvider() {
    
  override fun onCreateSliceProvider(): Boolean {
      return true
  }

  override fun onMapIntentToUri(intent: Intent?): Uri {

      var uriBuilder: Uri.Builder = Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
      if (intent == null) return uriBuilder.build()
      val data = intent.data
      if (data != null && data.path != null) {
          val path = data.path.replace("/", "")
          uriBuilder = uriBuilder.path(path)
      }
      val context = context
      if (context != null) {
          uriBuilder = uriBuilder.authority(context.getPackageName())
      }
      return uriBuilder.build()
  }

//Construct the slice//

  override fun onBindSlice(sliceUri: Uri): Slice? {
      val context = getContext() ?: return null
      return if (sliceUri.path == "/") {

//Customise the Slice//

          ListBuilder(context, sliceUri)
                  .addRow { it.setTitle("URI found.") }
                  .build()
      } else {
          
          ListBuilder(context, sliceUri)
                  .addRow { it.setTitle("URI not found.") }
                  .build()
      }
  }

//Subscribe to a data source, if necessary//

  override fun onSlicePinned(sliceUri: Uri?) {

  }

//Avoid memory leaks by unsubscribing from the data source and removing any observers//

  override fun onSliceUnpinned(sliceUri: Uri?) {
  }
}

If you create your slice provider using New > Other > Slice Provider , then Android Studio will also add the necessary provider to your Manifest: 

<provider
       android:name=".MySliceProvider"
       android:authorities="com.jessicathornsby.kotlinslices"
       android:exported="true">
       <intent-filter>
           <action android:name="android.intent.action.VIEW" />
           
           <category android:name="android.app.slice.category.SLICE" />

           <data
               android:host="jessicathornsby.com"
               android:pathPrefix="/"
               android:scheme="http" />
       </intent-filter>
   </provider>
</application>

This entry ensures that your slice can be discovered by other applications.

Has Your Gradle Project Sync Failed?

So far, we’ve only used code that Android Studio has generated automatically, but your project may already be refusing to compile! 

Bugs, missing functionality and all-around strange behaviour are just part of the fun of working with early releases. At the time of writing, generating a slice provider would sometimes inexplicably add a new set of dependencies to your project’s build.gradle file. 

implementation 'androidx.slice:slices-core:1.0.0-alpha1'
implementation 'androidx.slice:slices-builders:1.0.0-alpha1'

Not only are these dependencies unnecessary—they’re wrong. Although it’s easy to miss, compare: 

implementation 'androidx.slice:slices-core:1.0.0-alpha3'

With the correct:

implementation 'androidx.slice:slice-core:1.0.0-alpha1'

A single s can mean the difference between a functioning application and a project that refuses to compile. Chances are this bug will be addressed before the official release of slices, but if Android Studio starts complaining about unresolved dependencies then check your build.gradle file to see whether this has happened in your project. 

Building a Slice: URIs, SliceActions , and Slice Layouts

To turn the slice provider’s boilerplate code into a functioning slice, we need to make several changes:

1. Define a URI

Each slice has a unique URI, and it’s the slice provider’s job to provide the mapping between this URI and the corresponding slice.

Apps that are capable of displaying a slice are known as host applications. Every time a host needs to display a slice, it sends a binding request to the slice provider with the URI of the slice that it’s looking for. Your slice provider will then check the URI and return the appropriate slice.

In the following snippet, the onBindSlice method is checking for the /myURI path and returning a slice that displays a  Hello World message.

class MySliceProvider : SliceProvider() {
    
   override fun onCreateSliceProvider(): Boolean {
       return true
   }

   override fun onBindSlice(sliceUri: Uri): Slice? {
       return if (sliceUri.path == "/myURI") {
           ListBuilder(context, sliceUri, ListBuilder.INFINITY)
                   .addRow { it.setTitle("Hello World") }
                   .build()
       } else {
...
...
...
       }
   }
}

2. Make Your Slice Interactive

While you could create a slice that simply displays some information, if you want your slice to be interactive then you’ll need to create one or more SliceActions

A SliceAction can consist of a title, an icon, and a PendingIntent . You can also mark SliceActions as primary actions , which trigger whenever the user taps anywhere on that slice’s row. 

3. Build the Slice’s UI

You define a slice’s layout by implementing a ListBuilder , adding a row, and then adding items to that row. For example, here I’m using ListBuilder and addRow to create a slice that consists of a title and a subtitle: 

import android.net.Uri
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder
import androidx.slice.builders.ListBuilder.INFINITY

class MySliceProvider : SliceProvider() {

   override fun onCreateSliceProvider(): Boolean {
       
       return true
   }

   override fun onBindSlice(sliceUri: Uri): Slice? {
       val path = sliceUri.path
       when (path) {
           "/launchMainActivity" -> return createSlice(sliceUri)
       }
       return null
   }

   fun createSlice(sliceUri: Uri): Slice {
       return ListBuilder(context, sliceUri, INFINITY)
               .addRow {
                   it.apply {
                       setTitle("This is a title")
                       setSubtitle("This is a subtitle")
                       
                   }
               }.build()
   }
  
}

You can display a mixture of different content types in the same row, such as text, actions, and icons.

Build Your First Fully Functioning Android Slice

Now let’s apply all of this to our project and create a slice that launches our application’s MainActivity when tapped. 

Open the MySliceProvider class, and add the following: 

import android.app.PendingIntent
import android.content.Intent
import android.net.Uri
import androidx.core.graphics.drawable.IconCompat
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder
import androidx.slice.builders.SliceAction

//Extend from SliceProvider//

class MySliceProvider : SliceProvider() {

//Initialise your slice provider//

  override fun onCreateSliceProvider(): Boolean {
      return true
  }

//Build the slice//

  override fun onBindSlice(sliceUri: Uri): Slice? {

//Check the URI path//

      val path = sliceUri.path
      when (path) {

//Define the slice’s URI; I’m using ‘launchMainActivity’//

          "/launchMainActivity" -> return createSlice(sliceUri)
      }
      return null
  }

  fun createSlice(sliceUri: Uri): Slice {
      val activityAction = createActivityAction()

//Create the ListBuilder, which we’ll use to add rows to our slice//

      val listBuilder = ListBuilder(context!!, sliceUri, ListBuilder.INFINITY)

//Construct the rows using RowBuilder//

      val rowBuilder = ListBuilder.RowBuilder(listBuilder)

//Set the title text//

              .setTitle("Open MainActivity.")

//Set the row’s primary action//

              .setPrimaryAction(activityAction)

//Add the row to the ListBuilder//

      listBuilder.addRow(rowBuilder)

//Build the list//

      return listBuilder.build()

  }

  fun createActivityAction(): SliceAction {
      val intent = Intent(context, MainActivity::class.java)
      return SliceAction(PendingIntent.getActivity(context, 0, intent, 0),
              IconCompat.createWithResource(context!!, R.drawable.ic_home),
              "Open MainActivity")
  }

}

Testing Your Slices: Installing Slice Viewer

If you’re going to put your slices to the test, then you’ll need at least one application that’s capable of displaying slices.

Slices will reportedly be making their debut in Google search later this year, but at the time of writing, this feature had yet to be rolled out. Currently, the only way to test slices is to install Google’s Slice Viewer app, which is designed to emulate how slices will eventually appear in Google search.

To install Slice Viewer on an Android Virtual Device (AVD):

To install Slice Viewer on a physical smartphone or tablet:

  • Download Slice Viewer .
  • Make sure your smartphone or tablet is attached to your development machine.
  • Move the Slice Viewer APK to your computer’s Android/sdk/platform-tools folder.
  • Open a Command Prompt (Windows) or Terminal (Mac) window. 
  • Change directory ( cd ) so that the Command Prompt or Terminal is pointing at your Android/sdk/platform-tools folder—for example, here's my command:
cd /Users/jessicathornsby/Library/Android/sdk/platform-tools
  • Run the command, by pressing the Enter key on your keyboard.
  • Use the adb install command to push the APK to your Android device:
./adb install slice-viewer.apk

Creating a URI Run Configuration

Next, you’ll need to create a run configuration that passes your slice’s unique URI to your AVD or Android device.

  • Select Run > Edit Configurations… from the Android Studio toolbar.
  • Click the + button and then select Android App .
bQVZbmA.png!web
  • Give your run configuration a name. I’m using sliceConfig
  • Open the Module dropdown, and then select app .
  • Open the Launch dropdown, and then select URL .
  • Enter your slice’s URL, in the format slice-content://package-name/slice-URL . For example, my slice’s URL is: slice-content://com.jessicathornsby.kotlinslices/launchMainActivity .
  • Click OK .
  • Select Run > Run sliceConfig from the Android Studio toolbar, and then select your Android device.

The first time Slice Viewer tries to display your slice, it’ll request permission to access your slice’s unique URI. Tap Allow and navigate the permissions dialogue, and your slice should appear onscreen.

RBreuia.png!web

To interact with the SliceAction , click the Open MainActivity button, and the slice will respond by launching your application’s MainActivity

Getting More Out of Your Slices: Adding a Second SliceAction

Why limit yourself to one SliceAction , when you can have multiple SliceActions ? In this section, we’re going to implement two SliceActions , where each action launches a different Activity . I’m also going to introduce a few new UI elements, by adding a subtitle and some end items to our slice. 

Create a SecondActivity

Let’s get the setup out of the way and create a second Activity that our second SliceAction can link to. 

First, select New > Kotlin File / Class from the Android Studio toolbar. In the new file dialog, open the Kind dropdown and select Class . Name this class SecondActivity , and then click OK

Now open your SecondActivity class and add the following:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class SecondActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_second)
   }
}

Next, select New > Android Resource File from the Android Studio toolbar. In the subsequent window, open the Resource type dropdown, and select  Layout . Name this file activity_second , and click OK

Now open this layout file and add the following code:

<?xml version="1.0" encoding="utf-8"?>
http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Second Activity"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Open your project’s Manifest, and declare this SecondActivity :

<activity android:name=".SecondActivity">

Building More Complex UIs: Slice End Items

End items can either be a timestamp, an image, or a SliceAction , but as the name suggests, they always appear at the end of a row. You can add multiple end items to a single row, although depending on the available space there’s no guarantee that all of your end items will be displayed to the user. 

We’ll be creating our SliceActions as icons, so you’ll need to add two new drawables to your project:

  • Select New > Image Asset from the Android Studio toolbar.
  • Click the little Clip art button (this displays a picture of an Android by default).
  • Select the icon that you want to use for your Launch MainActivity end item. I'm using the Home icon.
  • Give this icon the name ic_home , and then click Next .
  • Read the onscreen information, and if you’re happy to proceed then click Finish .

Repeat the above steps to create an icon for your Launch SecondActivity slice action. For my second end item, I'm using the call icon and naming it ic_call .

Creating the Second SliceAction

We’re now ready to add a second SliceAction to the MySliceProvider class: 

import android.app.PendingIntent
import android.content.Intent
import android.net.Uri
import androidx.core.graphics.drawable.IconCompat
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder
import androidx.slice.builders.SliceAction

class MySliceProvider : SliceProvider() {
    
  override fun onCreateSliceProvider(): Boolean {
      return true
  }

  override fun onBindSlice(sliceUri: Uri): Slice? {
      val path = sliceUri.path
      when (path) {
          "/launchMainActivity" -> return createSlice(sliceUri)
      }
      return null
  }

  fun createSlice(sliceUri: Uri): Slice {
      val activityAction = createActivityAction()
      IconCompat.createWithResource(context!!, R.drawable.ic_home).toIcon()
      val activityAction2 = createSecondActivityAction()
      IconCompat.createWithResource(context!!, R.drawable.ic_call).toIcon()

//Construct the parent builder//

          val listBuilder = ListBuilder(context!!, sliceUri)

//Construct the builder for the row//

          val myRow = ListBuilder.RowBuilder(listBuilder)
                  .setTitle("Launch MainActivity.")
                  .setSubtitle("This is a subtitle")

//Add the actions that we'll be using as end items//

          myRow.addEndItem(activityAction)
          myRow.addEndItem(activityAction2)

 //Add the row to the parent builder//

          listBuilder.addRow(myRow)

//Build the slice//

          return listBuilder.build()
      }

  fun createActivityAction(): SliceAction {
      val intent = Intent(context, MainActivity::class.java)
              return SliceAction(PendingIntent.getActivity(context, 0, intent, 0),
                      IconCompat.createWithResource(context!!, R.drawable.ic_home).toIcon(),
                      "Launch MainActivity")
  }

  fun createSecondActivityAction(): SliceAction {
      val intent = Intent(context, SecondActivity::class.java)
      return SliceAction(PendingIntent.getActivity(context, 0, intent, 0),
              IconCompat.createWithResource(context!!, R.drawable.ic_call).toIcon(),
              "Launch SecondActivity")
  }

}

Since we haven’t changed the URI, we don’t need to create a new run configuration, which means that testing this slice is as simple as selecting Run > sliceConfig from the Android Studio toolbar. 

neYbA3z.png!web

You can download this project from the tutorial GitHub repo. 

Multimedia Slices: Creating Grid Layouts

Up to this point, we’ve constructed all of our slices using rows only, but you can also build slices using grid rows and cells. 

In this final section, we’re going to create a slice consisting of a title, a subtitle, and a single row divided into three cells. Each cell will have its own title, some body text, and an image, and each one will perform a unique action when tapped.

MvUz2ez.png!web

To lay out your slice in a grid, you need to:

  • Implement a ListBuilder .
  • Add a grid row to the ListBuilder , using addGridRow
  • Add cells to the row, using addCell . Each row can display a maximum of five cells.

You can then add content to each cell, such as:

  • A title, which you add using addTitleText .
  • Body text, using addText .
  • Images, which you create using addImage . Each cell image must have one of the following attributes: LARGE_IMAGE , SMALL_IMAGE , or ICON_IMAGE
  • A content intent, which is roughly equivalent to a SliceAction . To help keep this example straightforward, tapping each cell will simply load an article in the device’s default browser, but if you’d prefer a more authentic slices experience then you can change the setContentIntent code. 

I’m going to include some images in my grid, so you’ll need to add at least one drawable to your project. I’m using the Kotlin logo, but you can grab any image and drop it into your project’s Drawable folder. 

Now, you’re ready to open the MySliceProvider class and build your grid: 

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.core.graphics.drawable.IconCompat
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder

class MySliceProvider : SliceProvider() {

    override fun onCreateSliceProvider(): Boolean {
        return true
    }

    override fun onBindSlice(sliceUri: Uri): Slice? {
        val path = sliceUri.path
        when (path) {
            "/launchMainActivity" -> return createSliceWithGridRow(sliceUri)
        }
        return null
    }

    fun createSliceWithGridRow(sliceUri: Uri): Slice {
        return ListBuilder(context, sliceUri, ListBuilder.INFINITY)
                .setHeader {
                    it.apply {
                        setTitle("Want to start learning Kotlin for Android?")
                        setSubtitle("Check out these articles!")
                    }
                }

//Add a grid row to the list builder//

                .addGridRow {
                    it.apply {

//Add a cell to the row//

                        addCell {
                            it.apply {

//Add content to your cell//

                                addTitleText("Java vs. Kotlin")
                                addText("Part 1")
                                addImage(IconCompat.createWithResource(context, R.drawable.kotlin), ListBuilder.LARGE_IMAGE)

//Specify the intent that should trigger whenever the user interacts with this cell//  


                                        .setContentIntent(
                                                loadArticlePendingIntent(
                                                        context,
                                                        "https://code.tutsplus.com/articles/java-vs-kotlin-should-you-be-using-kotlin-for-android-development...)
                            }
                        }
                        addCell {
                            it.apply {
                                addTitleText("Coding in Kotlin")
                                addText("Part 2")
                                addImage(IconCompat.createWithResource(context, R.drawable.kotlin), ListBuilder.LARGE_IMAGE)
                                        .setContentIntent(
                                                loadArticlePendingIntent(
                                                        context,
                                                        "https://code.tutsplus.com/tutorials/start-developing-android-apps-with-kotlin-part-1--cms-27827?_ga=...)
                            }
                        }

                        addCell {
                            it.apply {
                                addTitleText("Lambdas & NPE")
                                addText("Part 3")
                                addImage(IconCompat.createWithResource(context, R.drawable.kotlin), ListBuilder.LARGE_IMAGE)
                                        .setContentIntent(
                                                loadArticlePendingIntent(
                                                        context,
                                                        "https://code.tutsplus.com/articles/coding-functional-android-apps-in-kotlin-lambdas-null-safety-more...)
                            }
                        }
                    }
                }
                .build()
    }
    private fun loadArticlePendingIntent(context: Context, url: String) =
            PendingIntent.getActivity(
                    context,
                    0,
                    Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) },
                    0
            )
}

You can find the complete code for this project in our GitHub repo .

Run this app in your AVD or physical Android device, and try interacting with each item in the grid. Each cell should link to a different article.

Ensure Your Slice Looks Good, Regardless of the Host Application

The way your slice’s content is displayed can vary, depending on the mode the host application is configured for. To ensure your slices look good and function correctly regardless of the hosting application, you’ll need to test your slices across all the different slice modes.

Since our grid slice has significantly more content than the previous slices, it’s the best candidate to illustrate the differences between these various slice modes.

To put your slice to the test, click the little icon in the Slice Viewer’s upper-right corner, and then cycle through the following modes:

1. Large

In this format, Android displays as many rows as possible in the space available. This is the mode that Slice Viewer uses by default.

2. Shortcut

In this mode, your slice is represented by an icon and a label.

nAvEbm3.png!web

If there’s a primary header associated with your SliceAction , then this will be used as your slice’s icon. If there’s no icon available, then Android will instead display the primary action associated with your slice’s first row, which in this instance is our Kotlin drawable. 

To change the icon that’s displayed in shortcut mode, add a second drawable to your project, and then update the following section of the slice provider:

.addGridRow {
                   it.apply {
                       addCell {
                           it.apply {
                               addTitleText("Java vs. Kotlin")
                               addText("Part 1")

//Reference the new drawable//

                               addImage(IconCompat.createWithResource(context, R.drawable.androidlogo), ListBuilder.LARGE_IMAGE)

3. Small

Small mode has a restricted height and will either display a single SliceItem or a limited collection of items as a single row of content. If your slice has a header, then this will be displayed, which is exactly what’s happening with our slice. 

Bbmaiar.png!web

Changing either the title or the subtitle will affect the content that’s displayed in small mode.

fun createSliceWithGridRow(sliceUri: Uri): Slice {
   return ListBuilder(context, sliceUri, ListBuilder.INFINITY)
           .setHeader {
               it.apply {
               setTitle("This is the title")
               setSubtitle("This is the subtitle")
               
           }
       }

If your slice doesn’t contain a header, then the slice’s first row will be displayed instead.

Cut Down Code, With Slice Builders KTX

Once you’ve learned how to implement a new feature, the next step is learning how to deliver the same results, with less code!

Android KTX is a collection of modules consisting of extensions that optimize the Android platform for Kotlin. Android KTX’s Slice Builders KTX module wraps the builder pattern in a Kotlin-friendly DSL that helps you create your slices in a more concise, human-readable way. To get started with Slice Builders KTX, replace the following dependency:

implementation 'androidx.slice:slice-builders:1.0.0-alpha3'

With:

implementation 'androidx.slice:slice-builders-ktx:1.0.0-alpha3'

You can then modify your createSlice method to use this DSL. For example, here’s a simple slice that displays a title and a subtitle:

import android.net.Uri
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder
import androidx.slice.builders.ListBuilder.INFINITY

class MySliceProvider : SliceProvider() {

   override fun onCreateSliceProvider(): Boolean {
       return true
   }

   override fun onBindSlice(sliceUri: Uri): Slice? {
       val path = sliceUri.path
       when (path) {
           "/launchMainActivity" -> return createSlice(sliceUri)
       }
       return null
   }

   fun createSlice(sliceUri: Uri): Slice {
       return ListBuilder(context, sliceUri, INFINITY)
               .addRow {
                   it.apply {
                       setTitle("This is a title")
                       setSubtitle("This is a subtitle")

                   }
               }.build()
   }

}

Using the DSL, this becomes:

import android.net.Uri
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.slice.builders.ListBuilder
import androidx.slice.builders.list
import androidx.slice.builders.row

class MySliceProvider : SliceProvider() {

   override fun onCreateSliceProvider(): Boolean {
       return true
   }

   override fun onBindSlice(sliceUri: Uri): Slice? {
       val path = sliceUri.path
       when (path) {
           "/launchMainActivity" -> return createSlice(sliceUri)
       }
       return null
   }

   fun createSlice(sliceUri: Uri): Slice {

//Instantiate a ListBuilder and call build when the lambda has finished running//

       return list(context, sliceUri, ListBuilder.INFINITY) {

//Instantiate row and add it to the ListBuilder//

           row {

//setTitle and setSubtitle are both inside the row lambda//

               setTitle("This is a title")
               setSubtitle("This is a subtitle")

           }

       }
   }
}

Conclusion

In this article, we got some hands-on experience with Android’s up-and-coming slices feature. We saw how to create a simple slice that can provide direct access to any part of your application, before moving on to creating more complex slices consisting of end items, images, additional text, and multiple SliceActions

You can learn more about slices in the official Android docs. 


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK