Creare riquadri delle Impostazioni rapide personalizzati per la tua app

Le Impostazioni rapide sono riquadri visualizzati nel riquadro Impostazioni rapide, che rappresentano le azioni che gli utenti possono toccare per completare rapidamente le attività ricorrenti. La tua app può fornire un riquadro personalizzato agli utenti tramite la classe TileService e utilizzare un oggetto Tile per monitorare lo stato del riquadro. Ad esempio, puoi creare un riquadro che consenta agli utenti di attivare o disattivare una VPN fornita dalla tua app.

Riquadro Impostazioni rapide con il riquadro VPN attivato e disattivato
Figura 1. Riquadro Impostazioni rapide con il riquadro VPN attivato e disattivato.

Decidere quando creare un riquadro

Ti consigliamo di creare riquadri per funzionalità specifiche a cui ti aspetti che gli utenti accedano spesso o che necessitano di un accesso rapido (o a cui entrambi). I riquadri più efficaci sono quelli che corrispondono a entrambe le qualità e offrono un accesso rapido alle azioni eseguite di frequente.

Ad esempio, puoi creare un riquadro per un'app di fitness che consenta agli utenti di avviare rapidamente una sessione di allenamento. Tuttavia, non è consigliabile creare un riquadro per la stessa app che consenta agli utenti di rivedere l'intera cronologia dell'allenamento.

Casi d'uso dei riquadri dell'app per il fitness
Figura 2. Esempi di riquadri consigliati e non consigliati per un'app di fitness.

Per migliorare la rilevabilità e la facilità d'uso del riquadro, consigliamo di evitare alcune procedure:

  • Evita di usare i riquadri per avviare un'app. Usa una scorciatoia dell'app o un Avvio app standard.

  • Evita di usare i riquadri per azioni utente una tantum. Utilizza una scorciatoia app o una notifica.

  • Evita di creare troppi riquadri. Consigliamo un massimo di due per app. Usa invece una scorciatoia app.

  • Evita di utilizzare riquadri che mostrano informazioni, ma non sono interattivi per gli utenti. Utilizza una notifica o un widget.

Crea il tuo riquadro

Per creare un riquadro, devi prima creare un'icona riquadro appropriata, quindi creare e dichiarare TileService nel file manifest dell'app.

L'esempio di Impostazioni rapide fornisce un esempio di come creare e gestire un riquadro.

Crea la tua icona personalizzata

Dovrai fornire un'icona personalizzata che verrà visualizzata nel riquadro nel riquadro Impostazioni rapide. Aggiungerai questa icona quando dichiari l'oggetto TileService, come descritto nella prossima sezione. L'icona deve essere di colore bianco in tinta unita con uno sfondo trasparente, avere dimensioni di 24 x 24 dp e avere la forma di VectorDrawable.

Esempio di Drawable Vector
Figura 3. Esempio di disegno vettoriale.

Crea un'icona che suggerisca visivamente lo scopo del riquadro. Questo aiuta gli utenti a capire facilmente se il tuo riquadro è adatto alle loro esigenze. Ad esempio, puoi creare l'icona di un cronometro per un riquadro per un'app di fitness che consente agli utenti di avviare una sessione di allenamento.

Creare e dichiarare il proprio TileService

Crea un servizio per il tuo riquadro che estenda la classe TileService.

Kotlin

class MyQSTileService: TileService() {

  // Called when the user adds your tile.
  override fun onTileAdded() {
    super.onTileAdded()
  }
  // Called when your app can update your tile.
  override fun onStartListening() {
    super.onStartListening()
  }

  // Called when your app can no longer update your tile.
  override fun onStopListening() {
    super.onStopListening()
  }

  // Called when the user taps on your tile in an active or inactive state.
  override fun onClick() {
    super.onClick()
  }
  // Called when the user removes your tile.
  override fun onTileRemoved() {
    super.onTileRemoved()
  }
}

Java

public class MyQSTileService extends TileService {

  // Called when the user adds your tile.
  @Override
  public void onTileAdded() {
    super.onTileAdded();
  }

  // Called when your app can update your tile.
  @Override
  public void onStartListening() {
    super.onStartListening();
  }

  // Called when your app can no longer update your tile.
  @Override
  public void onStopListening() {
    super.onStopListening();
  }

  // Called when the user taps on your tile in an active or inactive state.
  @Override
  public void onClick() {
    super.onClick();
  }

  // Called when the user removes your tile.
  @Override
  public void onTileRemoved() {
    super.onTileRemoved();
  }
}

Dichiara TileService nel file manifest dell'app. Aggiungi il nome e l'etichetta del tuo TileService, l'icona personalizzata creata nella sezione precedente e l'autorizzazione appropriata.

 <service
     android:name=".MyQSTileService"
     android:exported="true"
     android:label="@string/my_default_tile_label"  // 18-character limit.
     android:icon="@drawable/my_default_icon_label"
     android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
     <intent-filter>
         <action android:name="android.service.quicksettings.action.QS_TILE" />
     </intent-filter>
 </service>

Gestire TileService

Dopo aver creato e dichiarato TileService nel file manifest dell'app, devi gestirne lo stato.

TileService è un servizio associato. TileService è vincolato quando richiesto dalla tua app o se il sistema deve comunicare con l'app. Un tipico ciclo di vita di bound-service include i seguenti quattro metodi di callback: onCreate(), onBind(), onUnbind() e onDestroy(). Questi metodi vengono richiamati dal sistema ogni volta che il servizio entra in una nuova fase del ciclo di vita.

Panoramica del ciclo di vita di TileService

Oltre ai callback che controllano il ciclo di vita di bound-service, devi implementare altri metodi specifici del ciclo di vita di TileService. Questi metodi possono essere chiamati al di fuori di onCreate() e onDestroy() perché i metodi del ciclo di vita Service e quelli del ciclo di vita TileService sono chiamati in due thread asincroni separati.

Il ciclo di vita di TileService contiene i seguenti metodi, che vengono richiamati dal sistema ogni volta che TileService entra in una nuova fase del ciclo di vita:

  • onTileAdded(): questo metodo viene chiamato solo quando l'utente aggiunge il riquadro per la prima volta e se l'utente lo rimuove e lo aggiunge di nuovo. Questo è il momento migliore per eseguire un'inizializzazione una tantum. Tuttavia, questa operazione potrebbe non soddisfare tutte le richieste di inizializzazione.

  • onStartListening() e onStopListening(): questi metodi vengono chiamati ogni volta che l'app aggiorna il riquadro e sono chiamati spesso. TileService rimane associato tra onStartListening() e onStopListening(), consentendo alla tua app di modificare il riquadro ed eseguire il push degli aggiornamenti.

  • onTileRemoved(): questo metodo viene richiamato solo se l'utente rimuove il tuo riquadro.

Seleziona una modalità di ascolto

Il tuo TileService ascolta in modalità attiva o non attiva. Ti consigliamo di utilizzare la modalità attiva, che devi dichiarare nel file manifest dell'app. In caso contrario, TileService è la modalità standard e non deve essere dichiarato.

Non dare per scontato che il tuo TileService vivrà al di fuori della coppia di metodi onStartListening() e onStopListening().

Utilizza la modalità attiva per un TileService che ascolta e monitora il proprio stato durante il proprio processo. Un TileService in modalità attiva è associato a onTileAdded(), onTileRemoved(), eventi di tocco e quando richiesto dal processo dell'app.

Ti consigliamo la modalità attiva se il tuo TileService riceve una notifica quando lo stato dei riquadri deve essere aggiornato con un proprio processo. I riquadri attivi limitano il carico sul sistema perché non devono essere associati ogni volta che il riquadro Impostazioni rapide diventa visibile all'utente.

È possibile chiamare il metodo statico TileService.requestListeningState() per richiedere l'inizio dello stato di ascolto e ricevere un callback a onStartListening().

Puoi dichiarare la modalità attiva aggiungendo META_DATA_ACTIVE_TILE al file manifest dell'app.

<service ...>
    <meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
         android:value="true" />
    ...
</service>

Modalità non attiva

La modalità non attiva è la modalità standard. Un TileService è in modalità non attiva se è associato ogni volta che il riquadro è visibile all'utente. Ciò significa che TileService potrebbe essere creato e associato di nuovo a volte al di fuori del suo controllo. Potrebbe inoltre essere non associato ed eliminato quando l'utente non visualizza il riquadro.

La tua app viene richiamata a onStartListening() dopo che l'utente ha aperto il riquadro Impostazioni rapide. Puoi aggiornare l'oggetto Tile tutte le volte che vuoi tra il giorno onStartListening() e il giorno onStopListening().

Non è necessario dichiarare la modalità non attiva: non è sufficiente aggiungere META_DATA_ACTIVE_TILE al file manifest dell'app.

Panoramica degli stati dei riquadri

Una volta aggiunto da un utente, il riquadro rimane sempre in uno dei seguenti stati.

  • STATE_ACTIVE: indica che è attivo o attivo. In questo stato, l'utente può interagire con il riquadro.

    Ad esempio, per il riquadro di un'app per l'attività fisica che consente agli utenti di avviare una sessione di allenamento a tempo, STATE_ACTIVE significa che l'utente ha avviato una sessione di allenamento e il timer è in esecuzione.

  • STATE_INACTIVE: indica uno stato spento o in pausa. In questo stato, l'utente può interagire con il riquadro.

    Per utilizzare di nuovo il riquadro dell'app per l'attività fisica, un riquadro in STATE_INACTIVE significa che l'utente non ha avviato una sessione di allenamento, ma potrebbe farlo se lo desidera.

  • STATE_UNAVAILABLE: indica uno stato temporaneamente non disponibile. In questo stato l'utente non può interagire con il riquadro.

    Ad esempio, un riquadro in STATE_UNAVAILABLE significa che il riquadro non è attualmente disponibile per l'utente per qualche motivo.

Il sistema imposta solo lo stato iniziale dell'oggetto Tile. Puoi impostare lo stato dell'oggetto Tile per il resto del suo ciclo di vita.

Il sistema potrebbe colorare l'icona e lo sfondo del riquadro per riflettere lo stato dell'oggetto Tile. Tile oggetti impostati su STATE_ACTIVE sono i più scuri, con STATE_INACTIVE e STATE_UNAVAILABLE sempre più chiari. La tonalità esatta è specifica per produttore e versione.

Riquadro VPN con colori per riflettere gli stati degli oggetti
Figura 4. Esempi di un riquadro colorato per riflettere lo stato del riquadro (rispettivamente attivo, inattivo e non disponibile).

Aggiornare il riquadro

Puoi aggiornare il riquadro quando ricevi una chiamata all'indirizzo onStartListening(). A seconda della modalità, il riquadro può essere aggiornato almeno una volta finché non viene ricevuto un callback a onStopListening().

In modalità attiva, puoi aggiornare il riquadro esattamente una volta prima di ricevere una chiamata a onStopListening(). In modalità non attiva, puoi aggiornare il riquadro tutte le volte che vuoi nel periodo compreso tra onStartListening() e onStopListening().

Puoi recuperare l'oggetto Tile chiamando getQsTile(). Per aggiornare i campi specifici dell'oggetto Tile, chiama i seguenti metodi:

Devi chiamare updateTile() per aggiornare il riquadro dopo aver impostato i valori corretti dei campi dell'oggetto Tile. In questo modo il sistema analizzerà i dati dei riquadri aggiornati e aggiornerà l'interfaccia utente.

Kotlin

data class StateModel(val enabled: Boolean, val label: String, val icon: Icon)

override fun onStartListening() {
  super.onStartListening()
  val state = getStateFromService()
  qsTile.label = state.label
  qsTile.contentDescription = tile.label
  qsTile.state = if (state.enabled) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.icon = state.icon
  qsTile.updateTile()
}

Java

public class StateModel {
  final boolean enabled;
  final String label;
  final Icon icon;

  public StateModel(boolean e, String l, Icon i) {
    enabled = e;
    label = l;
    icon = i;
  }
}

@Override
public void onStartListening() {
  super.onStartListening();
  StateModel state = getStateFromService();
  Tile tile = getQsTile();
  tile.setLabel(state.label);
  tile.setContentDescription(state.label);
  tile.setState(state.enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setIcon(state.icon);
  tile.updateTile();
}

Gestire i tocchi

Gli utenti possono toccare il riquadro per attivare un'azione se si trova in STATE_ACTIVE o STATE_INACTIVE. Il sistema richiama il callback onClick() dell'app.

Quando l'app riceve un callback a onClick(), può avviare una finestra di dialogo o un'attività, attivare il lavoro in background o modificare lo stato del riquadro.

Kotlin

var clicks = 0
override fun onClick() {
  super.onClick()
  counter++
  qsTile.state = if (counter % 2 == 0) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.label = "Clicked $counter times"
  qsTile.contentDescription = qsTile.label
  qsTile.updateTile()
}

Java

int clicks = 0;

@Override
public void onClick() {
  super.onClick();
  counter++;
  Tile tile = getQsTile();
  tile.setState((counter % 2 == 0) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setLabel("Clicked " + counter + " times");
  tile.setContentDescription(tile.getLabel());
  tile.updateTile();
}

Apri una finestra di dialogo

showDialog() comprime il riquadro Impostazioni rapide e mostra una finestra di dialogo. Utilizza una finestra di dialogo per aggiungere contesto all'azione se richiede un input aggiuntivo o il consenso dell'utente.

Avvia un'attività

startActivityAndCollapse() avvia un'attività durante la compressione del riquadro. Le attività sono utili se ci sono informazioni più dettagliate da visualizzare rispetto a una finestra di dialogo o se l'azione è molto interattiva.

Se l'app richiede un'interazione utente significativa, deve avviare un'attività solo come ultima risorsa. In alternativa, valuta la possibilità di utilizzare una finestra di dialogo o un pulsante di attivazione/disattivazione.

Se tocchi a lungo un riquadro, viene visualizzata la schermata Informazioni app per l'utente. Per ignorare questo comportamento e avviare un'attività per l'impostazione delle preferenze, aggiungi un <intent-filter> a una delle tue attività con ACTION_QS_TILE_PREFERENCES.

Contrassegna il tuo riquadro come attivabile

Ti consigliamo di contrassegnare il riquadro come attivabile se funziona principalmente come interruttore a due stati (il comportamento più comune dei riquadri). Ciò consente di fornire informazioni sul comportamento del riquadro al sistema operativo e di migliorare l'accessibilità generale.

Imposta i metadati TOGGLEABLE_TILE su true per contrassegnare il riquadro come attivabile.

<service ...>
  <meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
    android:value="true" />
</service>

Esegui azioni sicure solo sui dispositivi bloccati in modo sicuro

Il riquadro potrebbe essere visualizzato nella parte superiore della schermata di blocco sui dispositivi bloccati. Se il riquadro contiene informazioni sensibili, controlla il valore di isSecure() per determinare se il dispositivo è in stato sicuro e TileService dovrebbe modificare il suo comportamento di conseguenza.

Se è sicuro eseguire l'azione del riquadro mentre è bloccato, usa startActivity() per avviare un'attività nella parte superiore della schermata di blocco.

Se l'azione del riquadro non è sicura, usa unlockAndRun() per richiedere all'utente di sbloccare il dispositivo. Se l'esito è positivo, il sistema esegue l'oggetto Runnable che passi in questo metodo.

Chiedi all'utente di aggiungere il tuo riquadro

Per aggiungere manualmente il riquadro, gli utenti devono seguire diversi passaggi:

  1. Scorri verso il basso per aprire il riquadro Impostazioni rapide.
  2. Tocca il pulsante Modifica.
  3. Scorri tutti i riquadri sul loro dispositivo fino a quando non individua il tuo riquadro.
  4. Tieni premuto il riquadro e trascinalo nell'elenco dei riquadri attivi.

L'utente può anche spostare o rimuovere il riquadro in qualsiasi momento.

A partire da Android 13, puoi utilizzare il metodo requestAddTileService() per semplificare l'aggiunta del riquadro a un dispositivo da parte degli utenti. Questo metodo chiede agli utenti di aggiungere rapidamente il tuo riquadro direttamente al riquadro Impostazioni rapide. Il prompt include il nome dell'applicazione, l'etichetta e l'icona fornite.

Richiesta dell&#39;API Impostazioni rapide Placement
Figura 5. richiesta dell'API Impostazioni rapide Placement.
public void requestAddTileService (
  ComponentName tileServiceComponentName,
  CharSequence tileLabel,
  Icon icon,
  Executor resultExecutor,
  Consumer<Integer> resultCallback
)

Il callback contiene informazioni che indicano se il riquadro è stato aggiunto o meno, se era già presente o se si è verificato un errore.

Scegli con attenzione quando e con quale frequenza presentare la richiesta agli utenti. Ti consigliamo di chiamare requestAddTileService() solo nel contesto, ad esempio quando l'utente interagisce per la prima volta con una funzionalità facilitata dal tuo riquadro.

Il sistema può scegliere di interrompere l'elaborazione delle richieste per un determinato elemento ComponentName se è stato rifiutato dall'utente abbastanza volte. L'utente viene determinato in base alla metrica Context utilizzata per recuperare il servizio e deve corrispondere all'utente corrente.