Android 8.0 ha introdotto una nuova architettura delle informazioni per l'app Impostazioni per semplificare l'organizzazione delle impostazioni e consentire agli utenti di trovare rapidamente le impostazioni per personalizzare i propri dispositivi Android. Android 9 ha introdotto alcuni miglioramenti per fornire più funzionalità delle impostazioni e un'implementazione più semplice.
Esempi e origine
La maggior parte delle pagine delle impostazioni è attualmente implementata utilizzando il nuovo framework. Un buon
esempio è DisplaySettings:
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
Di seguito sono elencati i percorsi dei file per i componenti importanti:
- CategoryKey:
packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
- DashboardFragmentRegistry:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
- DashboardFragment:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
- AbstractPreferenceController:
frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
- BasePreferenceController (introdotto in Android 9):
packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java
Implementazione
I produttori di dispositivi sono invitati ad adattare l'architettura delle informazioni sulle impostazioni esistenti e a inserire pagine di impostazioni aggiuntive in base alle esigenze per ospitare funzionalità specifiche del partner. Lo spostamento delle preferenze dalla pagina legacy (implementata come
SettingsPreferencePage
) a una nuova pagina (implementata utilizzando
DashboardFragment
) può essere complicato. La preferenza della
pagina precedente probabilmente non è implementata con un PreferenceController
.
Pertanto, quando sposti una preferenza da una pagina legacy a una nuova pagina, devi creare un
PreferenceController
e spostare il codice nel controller prima di
istanziare il codice nel nuovo DashboardFragment
. Le API richieste da
PreferenceController
sono descritte nel nome e
documentate in Javadoc.
Ti consigliamo vivamente di aggiungere un test delle unità per ogni PreferenceController
.
Se la modifica viene inviata ad AOSP, è necessario un test delle unità.
Per ulteriori informazioni su come scrivere test basati su Robolectric, consulta il
file readme packages/apps/Settings/tests/robotests/README.md
.
Architettura dell'informazione in stile plug-in
Ogni elemento delle impostazioni viene implementato come preferenza. Una preferenza può essere facilmente spostata da una pagina all'altra.
Per facilitare lo spostamento di più impostazioni, Android 8.0 ha introdotto un fragment host in stile plug-in che contiene gli elementi delle impostazioni. Gli elementi delle impostazioni sono modellati come controller in stile plug-in. Pertanto, una pagina delle impostazioni è costituita da un unico frammento host e da più controller delle impostazioni.
DashboardFragment
DashboardFragment
è l'host dei controlli delle preferenze in stile plug-in.
Il frammento eredita da PreferenceFragment
e ha hook per
espandere e aggiornare sia gli elenchi delle preferenze statiche sia quelli dinamici.
Preferenze statiche
Un elenco di preferenze statico è definito in XML utilizzando il tag <Preference>
. Un'implementazione
DashboardFragment
utilizza il metodo
getPreferenceScreenResId()
per definire quale file XML contiene
l'elenco statico delle preferenze da visualizzare.
Preferenze dinamiche
Un elemento dinamico rappresenta un riquadro con un intento, che porta a un'attività esterna o interna. In genere, l'intent porta a una pagina delle impostazioni diversa. Ad esempio,
l'elemento di impostazione "Google" nella home page delle impostazioni è un elemento dinamico. Gli elementi dinamici sono definiti in AndroidManifest
(descritti di seguito) e caricati tramite un FeatureProvider
(definito come
DashboardFeatureProvider
).
Le impostazioni dinamiche sono più pesanti di quelle configurate staticamente, quindi in genere gli sviluppatori devono implementare l'impostazione come statica. Tuttavia, l'impostazione dinamica può essere utile quando si verifica una delle seguenti condizioni:
- L'impostazione non è implementata direttamente nell'app Impostazioni (ad esempio l'inserimento di un'impostazione implementata dalle app OEM/operatore).
- L'impostazione dovrebbe essere visualizzata nella home page delle impostazioni.
- Hai già un'attività per l'impostazione e non vuoi implementare la configurazione statica aggiuntiva.
Per configurare un'attività come impostazione dinamica:
- Contrassegna l'attività come impostazione dinamica aggiungendo un filtro per intent all'attività.
- Indica all'app Impostazioni a quale categoria appartiene. La categoria è una costante,
definita in
CategoryKey
. - (Facoltativo) Aggiungi un testo di riepilogo quando viene visualizzata l'impostazione.
Ecco un esempio tratto dall'app Impostazioni per DisplaySettings
.
<activity android:name="Settings$DisplaySettingsActivity" android:label="@string/display_settings" android:icon="@drawable/ic_settings_display"> <!-- Mark the activity as a dynamic setting --> <intent-filter> <action android:name="com.android.settings.action.IA_SETTINGS" /> </intent-filter> <!-- Tell Settings app which category it belongs to --> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.ia.homepage" /> <!-- Add a summary text when the setting is displayed --> <meta-data android:name="com.android.settings.summary" android:resource="@string/display_dashboard_summary"/> </activity>
Al momento del rendering, il fragment richiede un elenco di preferenze sia da XML statico sia dalle impostazioni dinamiche definite in AndroidManifest
. Indipendentemente dal fatto che i
PreferenceController
siano definiti nel codice Java o in XML,
DashboardFragment
gestisce la logica di gestione di ogni impostazione
tramite PreferenceController
(descritta di seguito). Vengono poi
visualizzati nell'interfaccia utente come un elenco misto.
PreferenceController
Esistono differenze tra l'implementazione di PreferenceController
in Android 9 e Android 8.x, come descritto in questa
sezione.
PreferenceController nella release di Android 9
Un PreferenceController
contiene tutta la logica per interagire con la preferenza, inclusi la visualizzazione, l'aggiornamento, l'indicizzazione della ricerca e così via.
L'interfaccia di PreferenceController
è definita come
BasePreferenceController
. Ad esempio, vedi il codice in
packages/apps/Settings/src/com/android/settings/core/
BasePreferenceController.java
Esistono diverse sottoclassi di BasePreferenceController
, ognuna
corrispondente a uno stile UI specifico supportato per impostazione predefinita dall'app Impostazioni. Ad esempio, TogglePreferenceController
ha un'API che esegue il mapping diretto al modo in cui l'utente deve interagire con un'interfaccia utente delle preferenze basata su un pulsante di attivazione/disattivazione.
BasePreferenceController
ha API come
getAvailabilityStatus()
, displayPreference()
,
handlePreferenceTreeClicked(),
e così via. La documentazione dettagliata per ogni
API si trova nella classe di interfaccia.
Una limitazione all'implementazione di BasePreferenceController
(e
delle relative sottoclassi, ad esempio TogglePreferenceController
) è che la
firma del costruttore deve corrispondere a una delle seguenti:
public MyController(Context context, String key) {}
public MyController(Context context) {}
Durante l'installazione di una preferenza nel fragmento, la dashboard fornisce un metodo per
allegare un PreferenceController
prima dell'ora di visualizzazione. Al momento dell'installazione,
il controller è collegato al fragment in modo che tutti gli eventi pertinenti futuri vengano
inviati al controller.
DashboardFragment
mantiene un elenco di
PreferenceController
sullo schermo. Nel onCreate()
del fragment, vengono richiamati tutti i controller per il metodo getAvailabilityStatus()
e, se restituisce true, viene richiamato displayPreference()
per elaborare la logica di visualizzazione.
getAvailabilityStatus()
è importante anche per comunicare al framework
delle impostazioni quali elementi sono disponibili durante la ricerca.
PreferenceController nelle release di Android 8.x
Un PreferenceController
contiene tutta la logica per interagire con la preferenza, inclusi visualizzazione, aggiornamento, indicizzazione della ricerca e così via.
In corrispondenza delle interazioni con le preferenze, l'interfaccia di
PreferenceController
dispone delle API isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
e così via.
La documentazione dettagliata su ogni API è disponibile nella classe dell'interfaccia.
Durante l'installazione di una preferenza nel fragmento, la dashboard fornisce un metodo per
allegare un PreferenceController
prima dell'ora di visualizzazione. Al momento dell'installazione,
il controller è collegato al fragment in modo che tutti gli eventi pertinenti futuri vengano
inviati al controller.
DashboardFragment
mantiene un elenco di PreferenceControllers
sullo schermo. Nel onCreate()
del fragment, tutti
i controller vengono richiamati per il metodo isAvailable()
e, se
restituisce true, viene richiamato displayPreference()
per elaborare la logica
di visualizzazione.
Utilizzare DashboardFragment
Spostare una preferenza dalla pagina A alla pagina B
Se la preferenza è elencata staticamente nel file XML delle preferenze della pagina originale, segui la procedura di spostamento statico per la tua versione di Android riportata di seguito. In caso contrario, segui la procedura di spostamento dinamico per la tua release Android.
Spostamento statico in Android 9
- Trova i file XML delle preferenze per la pagina originale e la pagina di destinazione. Puoi trovare queste informazioni nel metodo
getPreferenceScreenResId()
della pagina. - Rimuovi la preferenza dal file XML della pagina originale.
- Aggiungi la preferenza all'XML della pagina di destinazione.
- Rimuovi
PreferenceController
per questa preferenza dall'implementazione Java della pagina originale. Di solito si trova increatePreferenceControllers()
. Il controller potrebbe essere dichiarato direttamente in XML.Nota: la preferenza potrebbe non avere un
PreferenceController
. - Crea un'istanza di
PreferenceController
nelcreatePreferenceControllers()
della pagina di destinazione. Se ilPreferenceController
è definito in XML nella pagina precedente, definiscilo anche in XML per la nuova pagina.
Spostamento dinamico in Android 9
- Trova la categoria in cui sono ospitate la pagina originale e quella di destinazione. Puoi
trovare queste informazioni in
DashboardFragmentRegistry
. - Apri il file
AndroidManifest.xml
che contiene l'impostazione che devi spostare e trova la voce Attività che rappresenta questa impostazione. - Imposta il valore dei metadati dell'attività per
com.android.settings.category
sulla chiave della categoria della nuova pagina.
Spostamento statico nelle release di Android 8.x
- Trova i file XML delle preferenze per la pagina originale e la pagina di destinazione. Puoi trovare queste informazioni nel metodo
- Rimuovi la preferenza nel file XML della pagina originale.
- Aggiungi la preferenza all'XML della pagina di destinazione.
- Rimuovi
PreferenceController
per questa preferenza nell'implementazione Java della pagina originale. Di solito si trova ingetPreferenceControllers()
. - Crea un'istanza di
PreferenceController
nelgetPreferenceControllers()
della pagina di destinazione.
getPreferenceScreenResId()
della pagina.
Nota:è possibile che la preferenza non abbia un
PreferenceController
.
Spostamento dinamico nelle release di Android 8.x
- Trova la categoria in cui sono ospitate la pagina originale e quella di destinazione. Puoi trovare
queste informazioni in
DashboardFragmentRegistry
. - Apri il file
AndroidManifest.xml
che contiene l'impostazione che devi spostare e trova la voce Attività che rappresenta questa impostazione. - Modifica il valore dei metadati dell'attività per
com.android.settings.category
, imposta il valore in modo che punti alla chiave della categoria della nuova pagina.
Creare una nuova preferenza in una pagina
Se la preferenza è elencata in modo statico nel file XML delle preferenze della pagina originale, segui la procedura statica riportata di seguito. In caso contrario, segui la procedura dinamica.
Crea una preferenza statica
- Trova i file XML delle preferenze per la pagina. Puoi trovare queste informazioni dal metodo getPreferenceScreenResId() della pagina.
- Aggiungi un nuovo elemento Preference in XML. Assicurati che abbia un
android:key
univoco. -
Definisci un
PreferenceController
per questa preferenza nel metodogetPreferenceControllers()
della pagina.- In Android 8.x e, facoltativamente, in Android 9,
crea un'istanza di
PreferenceController
per questa preferenza nel metodocreatePreferenceControllers()
della pagina.Se questa preferenza esisteva già in altri luoghi, è possibile che esista già una
PreferenceController
. Puoi riutilizzarePreferenceController
senza crearne uno nuovo. -
A partire da Android 9, puoi scegliere di dichiarare
PreferenceController
in XML accanto alla preferenza. Ad esempio:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/>
- In Android 8.x e, facoltativamente, in Android 9,
crea un'istanza di
Creare una preferenza dinamica
- Trova la categoria in cui sono ospitate la pagina originale e quella di destinazione. Puoi trovare
queste informazioni in
DashboardFragmentRegistry
. - Crea una nuova attività in
AndroidManifest
- Aggiungi i metadati necessari alla nuova attività per definire l'impostazione. Imposta il valore dei metadati per
com.android.settings.category
sullo stesso valore definito nel passaggio 1.
Crea una nuova pagina
- Crea un nuovo frammento, ereditando da
DashboardFragment
. - Definisci la categoria in
DashboardFragmentRegistry
.Nota: questo passaggio è facoltativo. Se non hai bisogno di preferenze dinamiche in questa pagina, non devi fornire una chiave di categoria.
- Segui i passaggi per aggiungere le impostazioni necessarie per questa pagina. Per ulteriori informazioni, consulta la sezione Implementazione.
Convalida
- Esegui i test Robolectric nelle Impostazioni. Tutti i test esistenti e nuovi devono superare il controllo.
- Crea e installa Impostazioni, quindi apri manualmente la pagina in fase di modifica. La pagina dovrebbe aggiornarsi immediatamente.