Guida introduttiva

Questa pagina mostra come configurare l'ambiente e creare Sezioni nell'app.

Nota: Android Studio 3.2 o versioni successive contiene ulteriori strumenti e funzionalità utili per lo sviluppo delle sezioni:

  • Strumento di refactoring di AndroidX: obbligatorio se lavori in un progetto che usa le librerie AndroidX.
  • Sezioni i controlli dei lint: individua le pratiche anti-pratiche più comuni durante la creazione Sezioni
  • Modello SliceProvider: gestisce il boilerplate quando in fase di creazione di un SliceProvider

Scarica e installa il visualizzatore sezioni

Scarica l'anteprima più recente Release dell'APK Visualizzatore sezione che puoi usare per testare le sezioni senza implementare API SliceView.

Se ADB non è configurato correttamente nel tuo ambiente, consulta Guida ADB per ulteriori informazioni.

Installa il visualizzatore sezioni sul tuo dispositivo eseguendo il comando seguente nel stessa directory del file slice-viewer.apk scaricato:

adb install -r -t slice-viewer.apk

Esecuzione del visualizzatore sezioni

Puoi avviare il visualizzatore sezioni dal tuo progetto Android Studio o da la riga di comando:

Avvia Slice Viewer dal tuo progetto Android Studio

  1. Nel progetto, seleziona Esegui > Modifica configurazioni...
  2. Nell'angolo in alto a sinistra, fai clic sul segno più verde.
  3. Seleziona App per Android

  4. Inserisci sezione nel campo del nome.

  5. Seleziona il modulo dell'app nel menu a discesa Modulo

  6. In Opzioni di avvio, seleziona URL dal menu a discesa Avvia.

  7. Inserisci slice-<your slice URI> nel campo URL

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

  8. Fai clic su OK.

di Gemini Advanced.

Avvia lo strumento Visualizzatore sezioni tramite ADB (riga di comando)

Esegui la tua app da Android Studio:

adb install -t -r <yourapp>.apk

Visualizza la sezione eseguendo questo comando:

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

Visualizzatore sezione che mostra una singola sezione Wi-Fi

Visualizza tutte le sezioni in un unico posto

Oltre ad avviare una singola sezione, puoi visualizzare un elenco persistente dei tuoi Sezioni.

  • Utilizza la barra di ricerca per cercare manualmente le sezioni tramite URI (ad esempio, content://com.example.android.app/hello). Ogni volta che esegui una ricerca, la sezione viene aggiunto all'elenco.
  • Ogni volta che avvii lo strumento Visualizzatore sezioni con un URI sezione, la sezione viene aggiunta nell'elenco.
  • Puoi far scorrere una sezione per rimuoverla dall'elenco.
  • Tocca l'URI della sezione per visualizzare una pagina contenente solo quella sezione. Questo ha lo stesso effetto dell'avvio del visualizzatore sezione con un URI sezione.
di Gemini Advanced.

Visualizzatore sezioni che mostra un elenco di sezioni

Visualizza la sezione in diverse modalità

Un'app che presenta una sezione può modificare SliceView#mode in fase di runtime, quindi devi assicurarti che la sezione abbia l'aspetto previsto in ogni modalità. Seleziona l'icona del menu nell'area in alto a destra della pagina per cambiare modalità.

Visualizzatore a sezione singola con modalità impostata su "small"

Crea la tua prima sezione

Per creare una sezione, apri il tuo progetto Android Studio, fai clic con il tasto destro del mouse sulla src pacchetto e seleziona Nuovo... &gt; Altro > Slice Provider. Viene creato un corso che estende SliceProvider, aggiunge la voce del fornitore richiesta per il tuo AndroidManifest.xml e modifica i tuoi build.gradle per aggiungere le dipendenze di Slice richieste.

La modifica a AndroidManifest.xml è mostrata di seguito:

<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>

Le seguenti dipendenze vengono aggiunte a build.gradle:

Kotlin

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

Java

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

A ogni sezione è associato un URI. Quando una piattaforma vuole visualizzare una sezione, invia una richiesta di associazione alla tua app con questo URI. L'app gestisce quindi questo e crea dinamicamente la sezione tramite onBindSlice . La superficie può quindi visualizzare la Sezione quando opportuno.

Di seguito è riportato un esempio di un metodo onBindSlice che verifica l'URI /hello percorso e restituisce una sezione 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();
}

Utilizza la configurazione di esecuzione sezione creata nella sezione Visualizzatore sezioni precedente, passando l'URI della sezione (ad esempio, slice-content://com.android.example.slicesample/hello) di Hello World Sezione per visualizzarla nel visualizzatore sezioni.

Sezioni interattive

Come per le notifiche, puoi gestire i clic all'interno della sezione allegando PendingIntent oggetti che sono attivata al momento dell'interazione dell'utente. L'esempio riportato di seguito inizia Activity che può riceverle e gestirle intent:

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"
    );
}

Le sezioni supportano anche altri tipi di input, come i pulsanti di attivazione/disattivazione, che includono lo stato l'intent inviato all'app.

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);
}

Il destinatario può quindi verificare lo stato che riceve:

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();
        }
    }
}

Sezioni dinamiche

Le sezioni possono anche includere contenuti dinamici. Nell'esempio seguente, la funzionalità Sezione ora include il numero di trasmissioni ricevute nei suoi contenuti:

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);
}

In questo esempio, anche se viene mostrato, il conteggio non si aggiorna automaticamente. Puoi modificare il broadcast receiver per notificare al sistema che si è verificata una modifica utilizzando 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);
        }
    }
}

Modelli

Le sezioni supportano svariati modelli. Per ulteriori dettagli sulle opzioni dei modelli e dei problemi, consulta la sezione Modelli.