Premiers pas

Cette page vous explique comment configurer votre environnement et créer Des segments d'application dans votre application.

Remarque: Android Studio 3.2 ou version ultérieure contient des outils et fonctionnalités qui peuvent vous aider à développer des segments d'application:

  • Outil de refactorisation AndroidX: obligatoire si vous travaillez dans un projet qui utilise les bibliothèques AndroidX.
  • Vérifications lint des segments d'application: détecte les anti-pratiques courantes lors de la compilation Segments d'application
  • Modèle SliceProvider: gère le code récurrent lorsque créer une SliceProvider

Télécharger et installer la visionneuse de segments d'application

Télécharger le dernier exemple Version de l'APK de segment d'application que vous pouvez utiliser pour tester vos segments d'application sans implémenter API SliceView.

Si ADB n'est pas configuré correctement dans votre environnement, consultez le Pour en savoir plus, consultez le guide ADB.

Installez la visionneuse de segments d'application sur votre appareil en exécutant la commande suivante dans la dans le même répertoire que le fichier slice-viewer.apk téléchargé:

adb install -r -t slice-viewer.apk

Exécuter le lecteur de segments d'application

Vous pouvez lancer la visionneuse de segments d'application à partir de votre projet Android Studio ou depuis la ligne de commande:

Lancer la visionneuse de segments d'application depuis votre projet Android Studio

  1. Dans votre projet, sélectionnez Run > Modifier les configurations...
  2. Dans le coin supérieur gauche, cliquez sur le signe plus vert
  3. Sélectionnez Application Android.

  4. Saisissez slice dans le champ "Nom".

  5. Sélectionnez votre module d'application dans la liste déroulante Module.

  6. Sous Options de lancement, sélectionnez URL dans le menu déroulant Lancement.

  7. Saisissez slice-<your slice URI> dans le champ d'URL.

    Exemple : slice-content://com.example.your.sliceuri

  8. Cliquez sur OK.

Lancer l'outil de visualisation de segments d'application via ADB (ligne de commande)

Exécutez votre application à partir d'Android Studio:

adb install -t -r <yourapp>.apk

Affichez votre segment d'application en exécutant la commande suivante:

adb shell am start -a android.intent.action.VIEW -d slice-<your slice URI>

Lecteur de segments d'application affichant un seul segment d'application Wi-Fi

Afficher tous vos segments d'application au même endroit

En plus de lancer un seul segment d'application, vous pouvez afficher une liste persistante Segments d'application.

  • Utilisez la barre de recherche pour rechercher manuellement vos segments d'application via l'URI (par exemple, content://com.example.android.app/hello). Chaque fois que vous effectuez une recherche, le segment d'application ajouté à la liste.
  • Chaque fois que vous lancez l'outil "Visionneuse de segments d'application" avec un URI de segment d'application, le segment d'application est ajouté à la liste.
  • Vous pouvez balayer un segment d'application pour le supprimer de la liste.
  • Appuyez sur l'URI du segment d'application pour afficher une page ne contenant que ce segment d'application. Il contient le même effet que le lancement du lecteur de segment d'application avec un URI de segment d'application.

Lecteur de segments d'application affichant une liste de segments d'application

Afficher le segment d'application dans différents modes

Une application qui présente un segment d'application peut modifier le SliceView#mode lors de l'exécution. Vous devez donc vous assurer que votre segment d'application s'affiche comme prévu dans chaque mode. Sélectionnez l'icône du menu en haut à droite de la page pour changer de mode.

Visionneuse de segments uniques avec le mode défini sur "petit"

Créer votre premier segment d'application

Pour créer un segment d'application, ouvrez votre projet Android Studio, effectuez un clic droit sur votre src package, puis sélectionnez Nouveau... &gt; Autre > Fournisseur de segments d'application. Cela crée une classe qui étend SliceProvider, ajoute l'entrée de fournisseur requise dans votre AndroidManifest.xml, et modifie votre build.gradle pour ajouter les dépendances de segments d'application requises.

La modification apportée à AndroidManifest.xml est illustrée ci-dessous:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.app">
    ...
    <application>
        ...
        <provider android:name="MySliceProvider"
            android:authorities="com.example.android.app"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.app.slice.category.SLICE" />
            </intent-filter>
        </provider>
        ...
    </application>

</manifest>

Les dépendances suivantes sont ajoutées à votre build.gradle:

Kotlin

dependencies {
// ...
    implementation "androidx.slice:slice-builders-ktx:(latest version)"
// ...
}

Java

dependencies {
// ...
    implementation "androidx.slice:slice-builders:(latest version)"
// ...
}

Chaque segment d'application est associé à un URI. Lorsqu'une surface souhaite afficher un segment d'application, envoie une demande de liaison à votre application avec cet URI. Votre application gère ensuite cela requête et crée le segment d'application de manière dynamique via onBindSlice . La surface peut ensuite afficher le segment d'application si nécessaire.

Vous trouverez ci-dessous un exemple de méthode onBindSlice qui vérifie l'URI /hello. et renvoie un segment d'application Hello World:

Kotlin

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 {
        list(context, sliceUri, ListBuilder.INFINITY) {
            row {
                primaryAction = activityAction
                title = "URI not recognized."
            }
        }
    }
}

Java

@Override
public Slice onBindSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    SliceAction activityAction = createActivityAction();
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    // Create parent ListBuilder.
    if ("/hello".equals(sliceUri.getPath())) {
        listBuilder.addRow(new ListBuilder.RowBuilder()
                .setTitle("Hello World")
                .setPrimaryAction(activityAction)
        );
    } else {
        listBuilder.addRow(new ListBuilder.RowBuilder()
                .setTitle("URI not recognized")
                .setPrimaryAction(activityAction)
        );
    }
    return listBuilder.build();
}

Utilisez la configuration d'exécution du slice que vous avez créée dans la section "Visionneuse de segments d'application". ci-dessus, en transmettant l'URI de votre segment d'application (par exemple, slice-content://com.android.example.slicesample/hello) de Hello World Segment d'application pour l'afficher dans la visionneuse de segments d'application.

Segments d'application interactifs

Comme pour les notifications, vous pouvez gérer les clics dans votre segment d'application en joignant Les objets PendingIntent qui sont déclenché par une interaction de l'utilisateur. L'exemple ci-dessous permet de lancer Activity pouvant les recevoir et les gérer intents:

Kotlin

fun createSlice(sliceUri: Uri): Slice {
    val activityAction = createActivityAction()
    return list(context, sliceUri, INFINITY) {
        row {
            title = "Perform action in app"
            primaryAction = activityAction
        }
    }
}

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

Java

public Slice createSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    SliceAction activityAction = createActivityAction();
    return new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .addRow(new ListBuilder.RowBuilder()
                    .setTitle("Perform action in app.")
                    .setPrimaryAction(activityAction)
            ).build();
}

public SliceAction createActivityAction() {
    if (getContext() == null) {
        return null;
    }
    return SliceAction.create(
            PendingIntent.getActivity(
                    getContext(),
                    0,
                    new Intent(getContext(), MainActivity.class),
                    0
            ),
            IconCompat.createWithResource(getContext(), R.drawable.ic_home),
            ListBuilder.ICON_IMAGE,
            "Enter app"
    );
}

Les segments d'application sont également compatibles avec d'autres types d'entrées, comme les boutons d'activation/de désactivation, qui incluent un état l'intent envoyé à l'application.

Kotlin

fun createBrightnessSlice(sliceUri: Uri): Slice {
    val toggleAction =
        SliceAction.createToggle(
            createToggleIntent(),
            "Toggle adaptive brightness",
            true
        )
    return list(context, sliceUri, ListBuilder.INFINITY) {
        row {
            title = "Adaptive brightness"
            subtitle = "Optimizes brightness for available light"
            primaryAction = toggleAction
        }
        inputRange {
            inputAction = (brightnessPendingIntent)
            max = 100
            value = 45
        }
    }
}

fun createToggleIntent(): PendingIntent {
    val intent = Intent(context, MyBroadcastReceiver::class.java)
    return PendingIntent.getBroadcast(context, 0, intent, 0)
}

Java

public Slice createBrightnessSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    SliceAction toggleAction = SliceAction.createToggle(
            createToggleIntent(),
            "Toggle adaptive brightness",
            true
    );
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
            .addRow(new ListBuilder.RowBuilder()
                    .setTitle("Adaptive brightness")
                    .setSubtitle("Optimizes brightness for available light.")
                    .setPrimaryAction(toggleAction)
            ).addInputRange(new ListBuilder.InputRangeBuilder()
                    .setInputAction(brightnessPendingIntent)
                    .setMax(100)
                    .setValue(45)
            );
    return listBuilder.build();
}

public PendingIntent createToggleIntent() {
    Intent intent = new Intent(getContext(), MyBroadcastReceiver.class);
    return PendingIntent.getBroadcast(getContext(), 0, intent, 0);
}

Le récepteur peut alors vérifier l'état qu'il reçoit:

Kotlin

class MyBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) {
            Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                    Slice.EXTRA_TOGGLE_STATE, false),
                    Toast.LENGTH_LONG).show()
        }
    }

    companion object {
        const val EXTRA_MESSAGE = "message"
    }
}

Java

public class MyBroadcastReceiver extends BroadcastReceiver {

    public static String EXTRA_MESSAGE = "message";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.hasExtra(EXTRA_TOGGLE_STATE)) {
            Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                    EXTRA_TOGGLE_STATE, false),
                    Toast.LENGTH_LONG).show();
        }
    }
}

Segments d'application dynamiques

Les segments d'application peuvent également contenir du contenu dynamique. Dans l'exemple suivant, le segment d'application comprend le nombre de diffusions reçues dans son contenu:

Kotlin

fun createDynamicSlice(sliceUri: Uri): Slice {
    return when (sliceUri.path) {
        "/count" -> {
            val toastAndIncrementAction = SliceAction.create(
                createToastAndIncrementIntent("Item clicked."),
                actionIcon,
                ListBuilder.ICON_IMAGE,
                "Increment."
            )
            list(context, sliceUri, ListBuilder.INFINITY) {
                row {
                    primaryAction = toastAndIncrementAction
                    title = "Count: ${MyBroadcastReceiver.receivedCount}"
                    subtitle = "Click me"
                }
            }
        }

        else -> {
            list(context, sliceUri, ListBuilder.INFINITY) {
                row {
                    primaryAction = createActivityAction()
                    title = "URI not found."
                }
            }
        }
    }
}

Java

public Slice createDynamicSlice(Uri sliceUri) {
    if (getContext() == null || sliceUri.getPath() == null) {
        return null;
    }
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    switch (sliceUri.getPath()) {
        case "/count":
            SliceAction toastAndIncrementAction = SliceAction.create(
                    createToastAndIncrementIntent("Item clicked."),
                    actionIcon,
                    ListBuilder.ICON_IMAGE,
                    "Increment."
            );
            listBuilder.addRow(
                    new ListBuilder.RowBuilder()
                            .setPrimaryAction(toastAndIncrementAction)
                            .setTitle("Count: " + MyBroadcastReceiver.sReceivedCount)
                            .setSubtitle("Click me")
            );
            break;
        default:
            listBuilder.addRow(
                    new ListBuilder.RowBuilder()
                            .setPrimaryAction(createActivityAction())
                            .setTitle("URI not found.")
            );
            break;
    }
    return listBuilder.build();
}

public PendingIntent createToastAndIncrementIntent(String s) {
    Intent intent = new Intent(getContext(), MyBroadcastReceiver.class)
            .putExtra(MyBroadcastReceiver.EXTRA_MESSAGE, s);
    return PendingIntent.getBroadcast(getContext(), 0, intent, 0);
}

Dans cet exemple, bien que le nombre soit affiché, il n'est pas mis à jour automatiquement. Vous pouvez Modifier votre broadcast receiver pour avertir le système qu'une modification a eu lieu en utilisant ContentResolver#notifyChange

Kotlin

class MyBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) {
            Toast.makeText(
                context, "Toggled:  " + intent.getBooleanExtra(
                    Slice.EXTRA_TOGGLE_STATE, false
                ),
                Toast.LENGTH_LONG
            ).show()
            receivedCount++;
            context.contentResolver.notifyChange(sliceUri, null)
        }
    }

    companion object {
        var receivedCount = 0
        val sliceUri = Uri.parse("content://com.android.example.slicesample/count")
        const val EXTRA_MESSAGE = "message"
    }
}

Java

public class MyBroadcastReceiver extends BroadcastReceiver {

    public static int sReceivedCount = 0;
    public static String EXTRA_MESSAGE = "message";

    private static Uri sliceUri = Uri.parse("content://com.android.example.slicesample/count");

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.hasExtra(EXTRA_TOGGLE_STATE)) {
            Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                    EXTRA_TOGGLE_STATE, false),
                    Toast.LENGTH_LONG).show();
            sReceivedCount++;
            context.getContentResolver().notifyChange(sliceUri, null);
        }
    }
}

Modèles

Les segments d'application sont compatibles avec divers modèles. Pour en savoir plus sur les options des modèles consultez la section Modèles.