Crea un autenticatore stub

Il framework dell'adattatore di sincronizzazione presuppone che trasferisca i dati tra lo spazio di archiviazione del dispositivo associato a un account e lo spazio di archiviazione del server che richiede l'accesso. Per questo motivo, il framework si aspetta che tu fornisca un componente chiamato autenticatore all'interno dell'adattatore di sincronizzazione. Questo componente si collega agli account e al framework di autenticazione Android e fornisce un'interfaccia standard per la gestione delle credenziali utente, ad esempio le informazioni di accesso.

Anche se la tua app non usa account, devi comunque fornire un componente di autenticazione. Se non utilizzi account o accesso al server, le informazioni gestite dall'autenticatore vengono ignorate, quindi puoi fornire un componente di autenticazione che contiene le implementazioni del metodo stub. Devi inoltre fornire un Service associato che consenta al framework dell'adattatore di sincronizzazione di chiamare i metodi dell'autenticatore.

Questa lezione spiega come definire tutte le parti di un autenticatore stub necessarie per soddisfare i requisiti del framework dell'adattatore di sincronizzazione. Se devi fornire un autenticatore reale che gestisca gli account utente, leggi la documentazione di riferimento per AbstractAccountAuthenticator.

Aggiungi un componente di autenticazione stub

Per aggiungere un componente di autenticazione stub alla tua app, crea una classe che estenda AbstractAccountAuthenticator, quindi analizza i metodi richiesti, restituendo null o generando un'eccezione.

Lo snippet seguente mostra un esempio di classe di autenticazione stub:

Kotlin

/*
 * Implement AbstractAccountAuthenticator and stub out all
 * of its methods
 */
class Authenticator(context: Context) // Simple constructor
    : AbstractAccountAuthenticator(context) {

    // Editing properties is not supported
    override fun editProperties(r: AccountAuthenticatorResponse, s: String): Bundle {
        throw UnsupportedOperationException()
    }

    // Don't add additional accounts
    @Throws(NetworkErrorException::class)
    override fun addAccount(
            r: AccountAuthenticatorResponse,
            s: String,
            s2: String,
            strings: Array<String>,
            bundle: Bundle
    ): Bundle?  = null

    // Ignore attempts to confirm credentials
    @Throws(NetworkErrorException::class)
    override fun confirmCredentials(
            r: AccountAuthenticatorResponse,
            account: Account,
            bundle: Bundle
    ): Bundle?  = null

    // Getting an authentication token is not supported
    @Throws(NetworkErrorException::class)
    override fun getAuthToken(
            r: AccountAuthenticatorResponse,
            account: Account,
            s: String,
            bundle: Bundle
    ): Bundle {
        throw UnsupportedOperationException()
    }

    // Getting a label for the auth token is not supported
    override fun getAuthTokenLabel(s: String): String {
        throw UnsupportedOperationException()
    }

    // Updating user credentials is not supported
    @Throws(NetworkErrorException::class)
    override fun updateCredentials(
            r: AccountAuthenticatorResponse,
            account: Account,
            s: String,
            bundle: Bundle
    ): Bundle {
        throw UnsupportedOperationException()
    }

    // Checking features for the account is not supported
    @Throws(NetworkErrorException::class)
    override fun hasFeatures(
            r: AccountAuthenticatorResponse,
            account: Account,
            strings: Array<String>
    ): Bundle {
        throw UnsupportedOperationException()
    }
}

Java

/*
 * Implement AbstractAccountAuthenticator and stub out all
 * of its methods
 */
public class Authenticator extends AbstractAccountAuthenticator {
    // Simple constructor
    public Authenticator(Context context) {
        super(context);
    }
    // Editing properties is not supported
    @Override
    public Bundle editProperties(
            AccountAuthenticatorResponse r, String s) {
        throw new UnsupportedOperationException();
    }
    // Don't add additional accounts
    @Override
    public Bundle addAccount(
            AccountAuthenticatorResponse r,
            String s,
            String s2,
            String[] strings,
            Bundle bundle) throws NetworkErrorException {
        return null;
    }
    // Ignore attempts to confirm credentials
    @Override
    public Bundle confirmCredentials(
            AccountAuthenticatorResponse r,
            Account account,
            Bundle bundle) throws NetworkErrorException {
        return null;
    }
    // Getting an authentication token is not supported
    @Override
    public Bundle getAuthToken(
            AccountAuthenticatorResponse r,
            Account account,
            String s,
            Bundle bundle) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
    // Getting a label for the auth token is not supported
    @Override
    public String getAuthTokenLabel(String s) {
        throw new UnsupportedOperationException();
    }
    // Updating user credentials is not supported
    @Override
    public Bundle updateCredentials(
            AccountAuthenticatorResponse r,
            Account account,
            String s, Bundle bundle) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
    // Checking features for the account is not supported
    @Override
    public Bundle hasFeatures(
        AccountAuthenticatorResponse r,
        Account account, String[] strings) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
}

Associa l'autenticatore al framework

Affinché il framework dell'adattatore di sincronizzazione possa accedere all'autenticatore, devi creare un servizio associato. Questo servizio fornisce un oggetto binder Android che consente al framework di chiamare l'autenticatore e trasferire dati tra quest'ultimo e il framework.

Lo snippet seguente mostra come definire il limite Service:

Kotlin

/**
* A bound Service that instantiates the authenticator
* when started.
*/
class AuthenticatorService : Service() {

    // Instance field that stores the authenticator object
    private lateinit var mAuthenticator: Authenticator

    override fun onCreate() {
        // Create a new authenticator object
        mAuthenticator = Authenticator(getApplicationContext())
    }

    /*
     * When the system binds to this Service to make the RPC call
     * return the authenticator's IBinder.
     */
    override fun onBind(intent: Intent?): IBinder = mAuthenticator.iBinder
}

Java

/**
 * A bound Service that instantiates the authenticator
 * when started.
 */
public class AuthenticatorService extends Service {
    ...
    // Instance field that stores the authenticator object
    private Authenticator mAuthenticator;
    @Override
    public void onCreate() {
        // Create a new authenticator object
        mAuthenticator = new Authenticator(getApplicationContext());
    }
    /*
     * When the system binds to this Service to make the RPC call
     * return the authenticator's IBinder.
     */
    @Override
    public IBinder onBind(Intent intent) {
        return mAuthenticator.getIBinder();
    }
}

Aggiungi il file di metadati dell'autenticatore

Per collegare il componente di autenticazione all'adattatore di sincronizzazione e ai framework dell'account, devi fornire a questo framework i metadati che descrivono il componente. Questi metadati dichiarano il tipo di account che hai creato per l'adattatore di sincronizzazione e gli elementi dell'interfaccia utente visualizzati dal sistema se vuoi rendere visibile il tipo di account all'utente. Dichiara questi metadati in un file XML archiviato nella directory /res/xml/ del progetto dell'app. Puoi assegnare qualsiasi nome al file, anche se di solito si chiama authenticator.xml.

Questo file XML contiene un singolo elemento <account-authenticator> con i seguenti attributi:

android:accountType
Il framework dell'adattatore di sincronizzazione richiede che ogni adattatore di sincronizzazione abbia un tipo di account, sotto forma di nome di dominio. Il framework utilizza il tipo di account nell'identificazione interna dell'adattatore di sincronizzazione. Per i server che richiedono l'accesso, il tipo di account e un account utente vengono inviati al server come parte delle credenziali di accesso.

Se il server non richiede l'accesso, devi comunque fornire un tipo di account. Per il valore, utilizza un nome di dominio controllato da te. Sebbene il framework lo utilizzi per gestire l'adattatore di sincronizzazione, il valore non viene inviato al server.

android:icon
Puntatore a una risorsa Drawable contenente un'icona. Se rendi visibile l'adattatore di sincronizzazione specificando l'attributo android:userVisible="true" in res/xml/syncadapter.xml, devi fornire questa risorsa icona. e riportato nella sezione Account dell'app Impostazioni del sistema.
android:smallIcon
Punta a una risorsa Drawable contenente una versione ridotta dell'icona. Questa risorsa potrebbe essere utilizzata al posto di android:icon nella sezione Account dell'app Impostazioni del sistema, a seconda delle dimensioni dello schermo.
android:label
Stringa localizzabile che identifica il tipo di account per gli utenti. Se rendi visibile l'adattatore di sincronizzazione specificando l'attributo android:userVisible="true" in res/xml/syncadapter.xml, devi fornire questa stringa. Viene visualizzata nella sezione Account dell'app Impostazioni del sistema, accanto all'icona che definisci per l'autenticatore.

Lo snippet seguente mostra il file XML dell'autenticatore che hai creato in precedenza:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:accountType="example.com"
        android:icon="@drawable/ic_launcher"
        android:smallIcon="@drawable/ic_launcher"
        android:label="@string/app_name"/>

Dichiara l'autenticatore nel file manifest

In un passaggio precedente, hai creato un Service associato che collega l'autenticatore al framework dell'adattatore di sincronizzazione. Per identificare questo servizio nel sistema, dichiaralo nel file manifest dell'app aggiungendo il seguente elemento <service> come elemento secondario di <application>:

    <service
            android:name="com.example.android.syncadapter.AuthenticatorService">
        <intent-filter>
            <action android:name="android.accounts.AccountAuthenticator"/>
        </intent-filter>
        <meta-data
            android:name="android.accounts.AccountAuthenticator"
            android:resource="@xml/authenticator" />
    </service>

L'elemento <intent-filter> configura un filtro che viene attivato dall'azione intent android.accounts.AccountAuthenticator, che viene inviato dal sistema per eseguire l'autenticatore. Quando viene attivato il filtro, il sistema avvia AuthenticatorService, il vincolo Service che hai fornito per eseguire il wrapping dell'autenticatore.

L'elemento <meta-data> dichiara i metadati per l'autenticatore. L'attributo android:name collega i metadati al framework di autenticazione. L'elemento android:resource specifica il nome del file di metadati dell'autenticatore che hai creato in precedenza.

Oltre a un autenticatore, un adattatore di sincronizzazione richiede anche un fornitore di contenuti. Se la tua app non utilizza già un fornitore di contenuti, vai alla lezione successiva per scoprire come creare un provider di contenuti stub; altrimenti, vai alla lezione Creazione di un adattatore di sincronizzazione.