Exploring Android Slices - JetPack

Introduction:

Slices are a new way of embedding our app's content in other surfaces, like Google Search and later in other places like Google Assistant. Slices are UI templates, which gives look and feel at home in whatever surface, they get hosts in. Also they are rich, interactive and dynamically updatable.

Before jumping into that, first migrate your project to AndroidX, (Android Studio 3.2 & above), by navigating as,

                                       Refactor --> Migrate  to AndroidX 



Setup:

build.gradle

    implementation 'androidx.slice:slice-core:1.0.0'
    implementation 'androidx.slice:slice-builders-ktx:1.0.0-alpha6'
    implementation 'androidx.slice:slice-builders:1.0.0'

Creating Slice Provider:

Slice Provider is a component that let us display the slices we are creating, on outside our application. We can create the Slice Provider by navigating,

                                      File -> New -> Other -> Slice Provider





A new Slice Provider Class got created. It have automatically generated code, that provides an overview. Also it will add a block of code in AndroidManifest as below.

AndroidManifest.xml 

       <provider
            android:name=".slices.MySliceProvider"
            android:authorities="com.yamikrish.app.sliceapp"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.app.slice.category.SLICE" />

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

Things to know:

                    Two things are more important to create the slices.

                                               (i) Slice Content
                                               (ii) Slice Action

(i) Slice Content:
Slice content is nothing, but UI of your slice. It can be dynamic and interactive with flexible UI.

(ii) Slice Action:

SliceAction consists of a label and PendingIntent and it may be IconButton or ToggleButton (default/custom).


MySliceProvider.kt

Lets create a simple slice, that have only title and subtitle.

package com.yamikrish.app.sliceapp.slices

import android.content.ContentResolver
import android.content.Intent
import android.net.Uri
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.core.graphics.drawable.IconCompat
import android.app.PendingIntent
import androidx.slice.builders.*
import androidx.slice.builders.ListBuilder.LARGE_IMAGE
import com.yamikrish.app.sliceapp.MainActivity
import com.yamikrish.app.sliceapp.R


class MySliceProvider : SliceProvider() {
    /**
     * Instantiate any required objects. Return true if the provider was successfully created,
     * false otherwise.
     */
    override fun onCreateSliceProvider(): Boolean {
        return true
    }

    /**
     * Converts URL to content URI (i.e. content://com.yamikrish.app.sliceapp...)
     */
    override fun onMapIntentToUri(intent: Intent?): Uri {
        // Note: implementing this is only required if you plan on catching URL requests.
        // This is an example solution.
        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.packageName)
        }
        return uriBuilder.build()
    }

    /**
     * Construct the Slice and bind data if available.
     */
    override fun onBindSlice(sliceUri: Uri): Slice? {
        // Note: you should switch your build.gradle dependency to
        // slice-builders-ktx for a nicer interface in Kotlin.
        val path = sliceUri.getPath();
        when (path) {

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

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

        //Create the ListBuilder - Normal Title & SubTitle//
        return list(context!!, sliceUri, ListBuilder.INFINITY) {
            row {
                title = "Test Launch!"
                subtitle = "Let's see how it works.. Just Click on it to proceed!!"
                primaryAction = activityAction
            }
        }
        
    }

    fun createActivityAction(): SliceAction {
        return SliceAction.create(
                PendingIntent.getActivity(
                        context, 0, Intent(context, MainActivity::class.java), 0
                ),
                IconCompat.createWithResource(context, R.drawable.ic_launcher_foreground),
                ListBuilder.ICON_IMAGE,
                "Open App"
        )
    }


    /**
     * Slice has been pinned to external process. Subscribe to data source if necessary.
     */
    override fun onSlicePinned(sliceUri: Uri?) {
        // When data is received, call context.contentResolver.notifyChange(sliceUri, null) to
        // trigger MySliceProvider#onBindSlice(Uri) again.
    }

    /**
     * Unsubscribe from data source if necessary.
     */
    override fun onSliceUnpinned(sliceUri: Uri?) {
        // Remove any observers if necessary to avoid memory leaks.
    }
}


(ii) With Image


package com.yamikrish.app.sliceapp.slices

import android.content.ContentResolver
import android.content.Intent
import android.net.Uri
import androidx.slice.Slice
import androidx.slice.SliceProvider
import androidx.core.graphics.drawable.IconCompat
import android.app.PendingIntent
import androidx.slice.builders.*
import androidx.slice.builders.ListBuilder.LARGE_IMAGE
import com.yamikrish.app.sliceapp.MainActivity
import com.yamikrish.app.sliceapp.R


class MySliceProvider : SliceProvider() {
    /**
     * Instantiate any required objects. Return true if the provider was successfully created,
     * false otherwise.
     */
    override fun onCreateSliceProvider(): Boolean {
        return true
    }

    /**
     * Converts URL to content URI (i.e. content://com.yamikrish.app.sliceapp...)
     */
    override fun onMapIntentToUri(intent: Intent?): Uri {
        // Note: implementing this is only required if you plan on catching URL requests.
        // This is an example solution.
        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.packageName)
        }
        return uriBuilder.build()
    }

    /**
     * Construct the Slice and bind data if available.
     */
    override fun onBindSlice(sliceUri: Uri): Slice? {
        // Note: you should switch your build.gradle dependency to
        // slice-builders-ktx for a nicer interface in Kotlin.
        val path = sliceUri.getPath();
        when (path) {

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

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

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

        //Create the ListBuilder - With Header and Image//
        return list(context!!, sliceUri, ListBuilder.INFINITY) {
            header { title = "Wanna Ride???" }
            gridRow {
                cell {
                    addImage(IconCompat.createWithResource(context, R.drawable.car), LARGE_IMAGE)
                }
            }
            row {
                title = "BOOK NOW"
                primaryAction = activityAction
            }
        }
    }

    fun createActivityAction(): SliceAction {
        return SliceAction.create(
                PendingIntent.getActivity(
                        context, 0, Intent(context, MainActivity::class.java), 0
                ),
                IconCompat.createWithResource(context, R.drawable.ic_launcher_foreground),
                ListBuilder.ICON_IMAGE,
                "Open App"
        )
    }


    /**
     * Slice has been pinned to external process. Subscribe to data source if necessary.
     */
    override fun onSlicePinned(sliceUri: Uri?) {
        // When data is received, call context.contentResolver.notifyChange(sliceUri, null) to
        // trigger MySliceProvider#onBindSlice(Uri) again.
    }

    /**
     * Unsubscribe from data source if necessary.
     */
    override fun onSliceUnpinned(sliceUri: Uri?) {
        // Remove any observers if necessary to avoid memory leaks.
    }
}



Test your slices:
To test your slices, you can install apk from the below site:
https://github.com/googlesamples/android-SliceViewer/releases

You can view the full project in GitHub, here.

Comments

  1. This comment has been removed by the author.

    ReplyDelete
  2. Thank you for sharing this informative post... Keep posting! Anyone interested in android app development for your business, contact us: +919500788278

    ReplyDelete
  3. I am really impressed with your blog article, such great & useful knowledge you mentioned here! Anyone interested build Kotlin app development for your business. let me help you. We at CodersNews provide 5 Best Ranked Kotlin Mobile App Development Companies which deliver feature-rich, simple yet sophisticated, and powerful applications across globe.

    ReplyDelete
  4. Your blog on reading is so full of great insights. I love your idea of adapting trade books. We have some that have far too much text, that would be fabulous, modified for our seven-year-old reader.
    Top IT Service in India

    ReplyDelete
  5. Nice article. Thank you for sharing such informative blog.
    Visit Mobibiz a leading mobile app development company in Gurgaon offers mobile and web development services for its regional and global clients. We deliver scalable and robust mobility solutions for all business segments.

    ReplyDelete
  6. Thanks for sharing this informative article on Exploring Android Slices - JetPack. If you want to Kotlin app development company for your project. Please visit us.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Are you an expert in remote front-end development with a love for readable, well-written code? Come work with us on state-of-the-art online apps while taking advantage of remote work's flexibility.
    hire remote web developer

    ReplyDelete
  9. Nice article. Great & useful knowledge you mentioned here! please keep sharing.

    Speaking of mobile app development, Maven Technology truly stands out as the Best Mobile App Development Company in Delhi. Our skilled developers, user-friendly designs, and commitment to quality make them the perfect choice.

    Call a technical App developer today at : +91 8851223376 , +13145144152 for detailed discussions.

    ReplyDelete

Post a Comment

Popular posts from this blog

SOAP Client using ksoap2 in Android - Kotlin

Databinding in RecyclerView - Android - Kotlin

Stripe Integration in Android - Kotlin

Exploring Android Navigation Architecture Component - MVVM - Kotlin

Braintree Integration in Android - Kotlin

Shimmer Layout like Facebook in Android - Kotlin

Map, Location update and AutoComplete Places - Kotlin

Firebase Storage - Upload Files - Kotlin

RecyclerView with different number of columns using SpanSizeLookup