Crea un host widget

La schermata Home di Android, disponibile sulla maggior parte dei dispositivi Android, consente all'utente di incorporare widget (o widget) di app per accedere rapidamente ai contenuti. Se vuoi creare una sostituzione della schermata Home o un'app simile, puoi anche consentire all'utente di incorporare i widget implementando AppWidgetHost. Per la maggior parte delle app questa operazione non è obbligatoria. Se invece ne crei uno, è importante comprendere le obbligazioni contrattuali che l'host accetta implicitamente.

Questa pagina è incentrata sulle responsabilità relative all'implementazione di un AppWidgetHost personalizzato. Per un esempio specifico di come implementare un AppWidgetHost, guarda il codice sorgente per la schermata Home di Android LauncherAppWidgetHost.

Ecco una panoramica delle classi e dei concetti principali coinvolti nell'implementazione di un AppWidgetHost personalizzato:

  • Host widget app: AppWidgetHost fornisce l'interazione con il servizio AppWidget per le app che incorporano widget nella propria UI. Un elemento AppWidgetHost deve avere un ID univoco all'interno del pacchetto dell'host. Questo ID persiste in tutti gli utilizzi dell'host. In genere l'ID è un valore impostato come hardcoded che assegni nell'app.

  • ID widget dell'app: a ogni istanza del widget viene assegnato un ID univoco al momento dell'associazione. Vedi bindAppWidgetIdIfAllowed() e, per ulteriori dettagli, consulta la sezione Associazione di widget che segue. L'host ottiene l'ID univoco utilizzando allocateAppWidgetId(). Questo ID persiste per tutta la durata del widget finché non viene eliminato dall'host. Qualsiasi stato specifico dell'host, come le dimensioni e la posizione del widget, deve essere mantenuto dal pacchetto di hosting e associato all'ID del widget dell'app.

  • Vista dell'host del widget dell'app: pensa a AppWidgetHostView come a un frame in cui il widget è aggregato ogni volta che deve essere visualizzato. Un widget è associato a un AppWidgetHostView ogni volta che l'host del widget viene gonfiato in modo artificioso.

    • Per impostazione predefinita, il sistema crea un AppWidgetHostView, ma l'host può creare la propria sottoclasse di AppWidgetHostView estendendola.
    • A partire da Android 12 (livello API 31), AppWidgetHostView introduce i metodi setColorResources() e resetColorResources() per gestire i colori sovraccarichi in modo dinamico. L'host è responsabile di fornire i colori a questi metodi.
  • Pacchetto di opzioni: AppWidgetHost utilizza il bundle di opzioni per comunicare a AppWidgetProvider informazioni su come viene visualizzato il widget, ad esempio l'elenco di intervalli di dimensioni, e se il widget si trova su una schermata di blocco o nella schermata Home. Queste informazioni consentono a AppWidgetProvider di personalizzare i contenuti e l'aspetto del widget in base a come e dove viene visualizzato. Puoi utilizzare updateAppWidgetOptions() e updateAppWidgetSize() per modificare il bundle di un widget. Entrambi i metodi attivano il callback onAppWidgetOptionsChanged() per AppWidgetProvider.

Widget di associazione

Quando un utente aggiunge un widget a un host, si verifica un processo chiamato associazione. L'associazione si riferisce all'associazione di un determinato ID widget dell'app a un host e a un AppWidgetProvider specifici.

L'associazione delle API consente inoltre a un host di fornire una UI personalizzata per l'associazione. Per utilizzare questa procedura, la tua app deve dichiarare l'autorizzazione BIND_APPWIDGET nel file manifest dell'host:

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

Ma questo è solo il primo passo. In fase di runtime, l'utente deve concedere esplicitamente l'autorizzazione all'app per consentirle di aggiungere un widget all'host. Per verificare se la tua app è autorizzata ad aggiungere il widget, usa il metodo bindAppWidgetIdIfAllowed(). Se bindAppWidgetIdIfAllowed() restituisce false, nell'app deve essere visualizzata una finestra di dialogo in cui viene chiesto all'utente di concedere l'autorizzazione: "consenti" per l'aggiunta del widget attuale o "consenti sempre" per coprire tutte le aggiunte future di widget.

Questo snippet fornisce un esempio di come visualizzare la finestra di dialogo:

Kotlin

val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply {
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName)
    // This is the options bundle described in the preceding section.
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options)
}
startActivityForResult(intent, REQUEST_BIND_APPWIDGET)

Java

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
// This is the options bundle described in the preceding section.
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET);

L'host deve verificare se è necessario configurare il widget aggiunto da un utente. Per maggiori informazioni, consulta Consentire agli utenti di configurare i widget di app.

Responsabilità dell'organizzatore

Puoi specificare una serie di impostazioni di configurazione per i widget utilizzando i metadati AppWidgetProviderInfo. Puoi recuperare queste opzioni di configurazione, trattate più dettagliatamente nelle sezioni seguenti, dall'oggetto AppWidgetProviderInfo associato a un provider di widget.

Indipendentemente dalla versione di Android scelta come target, tutti gli host hanno le seguenti responsabilità:

  • Quando aggiungi un widget, alloca il relativo ID come descritto in precedenza. Quando un widget viene rimosso dall'host, chiama deleteAppWidgetId() per deallocare l'ID widget.

  • Quando aggiungi un widget, controlla se è necessario avviare l'attività di configurazione. In genere, l'host deve avviare l'attività di configurazione del widget se esiste e non è contrassegnato come facoltativo specificando entrambi i flag configuration_optional e reconfigurable. Per maggiori dettagli, consulta Aggiornare il widget dall'attività di configurazione. Si tratta di un passaggio necessario per molti widget prima che possano essere visualizzati.

  • I widget specificano una larghezza e un'altezza predefinite nei metadati AppWidgetProviderInfo. Questi valori sono definiti nelle celle: a partire da Android 12, se targetCellWidth e targetCellHeight sono specificati, o dps se sono specificati solo minWidth e minHeight. Consulta Attributi per le dimensioni dei widget.

    Assicurati che il widget abbia almeno questo numero di dps. Ad esempio, molti host allineano icone e widget in una griglia. In questo scenario, per impostazione predefinita, l'host aggiunge un widget utilizzando il numero minimo di celle che soddisfano i vincoli minWidth e minHeight.

Oltre ai requisiti elencati nella sezione precedente, versioni specifiche della piattaforma introducono funzionalità che attribuiscono nuove responsabilità all'host.

Stabilisci il tuo approccio in base alla versione di Android target

Android 12

Android 12 (livello API 31) raggruppa un List<SizeF> aggiuntivo contenente l'elenco delle possibili dimensioni in dps che un'istanza di widget può assumere nel bundle di opzioni. Il numero di dimensioni fornite dipende dall'implementazione dell'host. Gli host in genere prevedono due dimensioni per gli smartphone: verticale e orizzontale e quattro per i pieghevoli.

Esiste un limite di MAX_INIT_VIEW_COUNT (16) al numero di RemoteViews diversi che un AppWidgetProvider può fornire a RemoteViews. Poiché gli oggetti AppWidgetProvider mappano un oggetto RemoteViews a ogni dimensione in List<SizeF>, non fornire più di MAX_INIT_VIEW_COUNT dimensioni.

Android 12 introduce anche gli attributi maxResizeWidth e maxResizeHeight in dps. Consigliamo di fare in modo che un widget che utilizza almeno uno di questi attributi non superi le dimensioni specificate dagli attributi.

Risorse aggiuntive

  • Consulta la documentazione di riferimento di Glance.