Android 8.0 ha introdotto una nuova architettura delle informazioni per l'app Impostazioni per semplificare il modo in cui sono organizzate le 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à Impostazioni e un'implementazione più semplice.
Esempi e fonte
La maggior parte delle pagine in Impostazioni sono attualmente implementate utilizzando il nuovo framework. Un buon esempio è DisplaySettings: packages/apps/Settings/src/com/android/settings/DisplaySettings.java
I percorsi dei file per i componenti importanti sono elencati di seguito:
- 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 incoraggiati ad adattare l'architettura informativa delle Impostazioni esistente e a inserire pagine di impostazioni aggiuntive secondo necessità per soddisfare le funzionalità specifiche dei 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 legacy probabilmente non è implementata con un PreferenceController
.
Pertanto, quando si spostano le preferenze da una pagina legacy a una nuova pagina, è necessario creare un PreferenceController
e spostare il codice nel controller prima di crearne un'istanza nel nuovo DashboardFragment
. Le API richieste PreferenceController
sono descritte nel loro nome e documentate in Javadoc.
Si consiglia vivamente di aggiungere un test unitario per ogni PreferenceController
. Se la modifica viene inviata ad AOSP, è richiesto un test unitario. Per ottenere ulteriori informazioni su come scrivere test basati su Robolectric, vedere il file readme packages/apps/Settings/tests/robotests/README.md
.
Architettura dell'informazione in stile plugin
Ciascun 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 frammento host in stile plug-in che contiene elementi di impostazione. Gli elementi delle impostazioni sono modellati come controller in stile plug-in. Pertanto, una pagina delle impostazioni è costruita da un singolo frammento host e più controller di impostazione.
DashboardFragment
DashboardFragment
è l'host di controller delle preferenze in stile plug-in. Il frammento eredita da PreferenceFragment
e dispone di hook per espandere e aggiornare sia gli elenchi di preferenze statiche che gli elenchi di preferenze dinamiche.
Preferenze statiche
Un elenco di preferenze statiche viene definito in XML utilizzando il tag <Preference>
. Un'implementazione DashboardFragment
utilizza il metodo getPreferenceScreenResId()
per definire quale file XML contiene l'elenco statico di preferenze da visualizzare.
Preferenze dinamiche
Un elemento dinamico rappresenta un riquadro con intento, che porta a un'attività esterna o interna. Di solito, l'intento porta a una pagina di impostazione diversa. Ad esempio, l'elemento di impostazione "Google" nella home page Impostazioni è un elemento dinamico. Gli elementi dinamici sono definiti in AndroidManifest
(descritto di seguito) e caricati tramite un FeatureProvider
(definito come DashboardFeatureProvider
).
Le impostazioni dinamiche sono più pesanti rispetto alle impostazioni configurate staticamente, quindi normalmente gli sviluppatori dovrebbero 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 inserendo un'impostazione implementata dalle app OEM/Operatore).
- L'impostazione dovrebbe essere visualizzata nella home page Impostazioni.
- Hai già un'attività per l'impostazione e non desideri implementare la configurazione statica aggiuntiva.
Per configurare un'attività come impostazione dinamica, procedere come segue:
- Contrassegna l'attività come impostazione dinamica aggiungendo un filtro di intenti all'attività.
- Indica all'app Impostazioni a quale categoria appartiene. La categoria è una costante, definita in
CategoryKey
. - Facoltativo: aggiungi 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 frammento richiederà un elenco di Preferenze sia dalle impostazioni XML statiche che 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 ciascuna impostazione tramite PreferenceController
(discusso di seguito). Quindi vengono visualizzati nell'interfaccia utente come un elenco misto.
PreferenceController
Esistono differenze tra l'implementazione PreferenceController
in Android 9 e Android 8.x, come descritto in questa sezione.
PreferenceController nella versione Android 9
Un PreferenceController
contiene tutta la logica per interagire con la preferenza, inclusa la visualizzazione, l'aggiornamento, l'indicizzazione della ricerca, ecc.
L'interfaccia di PreferenceController
è definita come BasePreferenceController
. Ad esempio, vedere il codice in packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java
Esistono diverse sottoclassi di BasePreferenceController
, ciascuna mappata a uno stile di interfaccia utente specifico supportato dall'app Impostazioni per impostazione predefinita. Ad esempio, TogglePreferenceController
dispone di un'API che si associa direttamente al modo in cui l'utente dovrebbe interagire con un'interfaccia utente delle preferenze basata su interruttore.
BasePreferenceController
dispone di API come getAvailabilityStatus()
, displayPreference()
, handlePreferenceTreeClicked(),
e così via. La documentazione dettagliata per ciascuna API si trova nella classe dell'interfaccia.
Una restrizione sull'implementazione BasePreferenceController
(e delle sue sottoclassi come TogglePreferenceController
) è che la firma del costruttore deve corrispondere a uno dei seguenti:
-
public MyController(Context context, String key) {}
-
public MyController(Context context) {}
Durante l'installazione di una preferenza sul frammento, la dashboard fornisce un metodo per collegare un PreferenceController
prima del tempo di visualizzazione. Al momento dell'installazione, il controller è collegato al frammento in modo che tutti gli eventi futuri rilevanti vengano inviati al controller.
DashboardFragment
mantiene un elenco di PreferenceController
sullo schermo. Nel frammento onCreate()
, tutti i controller vengono richiamati per il metodo getAvailabilityStatus()
e, se restituisce true, displayPreference()
viene richiamato per elaborare la logica di visualizzazione. getAvailabilityStatus()
è importante anche per indicare al framework Impostazioni quali elementi sono disponibili durante la ricerca. PreferenceController nelle versioni Android 8.x
Un PreferenceController
contiene tutta la logica per interagire con la preferenza, inclusa la visualizzazione, l'aggiornamento e l'indicizzazione della ricerca. eccetera.
In base alle interazioni delle preferenze, l'interfaccia di PreferenceController
dispone delle API isAvailable()
, displayPreference()
, handlePreferenceTreeClicked()
ecc. La documentazione dettagliata su ciascuna API può essere trovata nella classe dell'interfaccia.
Durante l'installazione di una preferenza sul frammento, la dashboard fornisce un metodo per collegare un PreferenceController
prima del tempo di visualizzazione. Al momento dell'installazione, il controller è collegato al frammento in modo che tutti gli eventi futuri rilevanti vengano inviati al controller.
DashboardFragment
mantiene un elenco di PreferenceControllers
sullo schermo. Nel frammento onCreate()
, tutti i controller vengono richiamati per il metodo isAvailable()
e, se restituisce true, displayPreference()
viene richiamato per elaborare la logica di visualizzazione.
Utilizzo di 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 Android di seguito. Altrimenti segui la procedura di spostamento dinamico relativa alla tua versione Android.
Movimento statico in Android 9
- Trova i file XML delle preferenze per la pagina originale e la pagina di destinazione. Puoi trovare queste informazioni dal metodo
getPreferenceScreenResId()
della pagina. - Rimuovi la preferenza dall'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 è 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. SePreferenceController
è definito in XML nella vecchia pagina, definiscilo in XML anche per la nuova pagina.
Movimento dinamico in Android 9
- Scopri quale categoria ospita 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 di categoria della nuova pagina.
Spostamento statico nelle versioni Android 8.x
- Trova i file XML delle preferenze per la pagina originale e la pagina di destinazione. Puoi trovare queste informazioni dal metodo
- Rimuovi la preferenza nell'XML della pagina originale.
- Aggiungi la preferenza all'XML della pagina di destinazione.
- Rimuovere
PreferenceController
per questa preferenza nell'implementazione Java della pagina originale. Di solito è ingetPreferenceControllers()
. - Crea un'istanza di
PreferenceController
nelgetPreferenceControllers()
della pagina di destinazione.
getPreferenceScreenResId()
della pagina. Nota : è possibile che la preferenza non disponga di un PreferenceController
.
Spostamento dinamico nelle versioni Android 8.x
- Scopri quale categoria ospita 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 sulla chiave di categoria della nuova pagina.
Creazione di una nuova preferenza in una pagina
Se la preferenza è elencata staticamente nel file XML delle preferenze della pagina originale, seguire la procedura statica riportata di seguito. Altrimenti seguire la procedura dinamica .
Creazione di 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 Preferenza nell'XML. Assicurati che abbia un
android:key
univoco. - Definire un
PreferenceController
per questa preferenza nel metodogetPreferenceControllers()
della pagina.- In Android 8.x e facoltativamente in Android 9, creare un'istanza di
PreferenceController
per questa preferenza nel metodocreatePreferenceControllers()
della pagina.Se questa preferenza esiste già in altri posti, è possibile che esista già un
PreferenceController
per essa. 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, creare un'istanza di
Creazione di una preferenza dinamica
- Scopri quale categoria ospita 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
. - Definire la sua categoria in
DashboardFragmentRegistry
.Nota: questo passaggio è facoltativo. Se non hai bisogno di preferenze dinamiche in questa pagina, non è necessario fornire una chiave di categoria.
- Segui i passaggi per aggiungere le impostazioni necessarie per questa pagina. Per ulteriori informazioni, vedere la sezione Implementazione .
Validazione
- Esegui i test robotelettrici nelle Impostazioni. Tutti i test esistenti e nuovi dovrebbero essere superati.
- Crea e installa Impostazioni, quindi apri manualmente la pagina da modificare. La pagina dovrebbe aggiornarsi immediatamente.