El framework del adaptador de sincronización prevé que tu adaptador de sincronización transfiere datos entre el almacenamiento del dispositivo asociado con una cuenta y el almacenamiento del servidor que requiere acceso. Por esta razón, el marco de trabajo espera que proporciones un componente llamado autenticador como parte de tu adaptador de sincronización. Este componente se conecta con las cuentas de Android y el marco de trabajo de autenticación, y proporciona una interfaz estándar para manejar las credenciales de los usuarios, como la información de acceso.
Incluso si tu app no usa cuentas, debes proporcionar un componente de autenticación.
Si no usas cuentas o acceso al servidor, se ignora la información que controla el autenticador, para que puedas proporcionar un componente de autenticador que contenga implementaciones del método stub. También debes proporcionar un Service
vinculado que permita que el framework del adaptador de sincronización llame a los métodos del autenticador.
En esta lección, se muestra cómo definir todas las partes de un autenticador de stub necesario para satisfacer los requisitos del framework del adaptador de sincronización. Si necesitas proporcionar un autenticador real que controle las cuentas de usuario, consulta la documentación de referencia de AbstractAccountAuthenticator
.
Cómo agregar un componente de autenticador de stub
Para agregar un componente de autenticador de stub a tu app, crea una clase que extienda AbstractAccountAuthenticator
y, luego, crea stubs de los métodos necesarios, ya sea mediante un resultado null
o arrojando una excepción.
En el siguiente fragmento, se muestra un ejemplo de una clase de autenticador de 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(); } }
Cómo vincular el autenticador con el marco de trabajo
Para que el marco de trabajo del adaptador de sincronización acceda a tu autenticador, debes crearle un servicio vinculado. Este servicio proporciona un objeto vinculante de Android que permite que el framework llame a tu autenticador y se pasen datos entre ambos.
Dado que el framework inicia este Service
la primera vez que accede al autenticador, también puedes usar el servicio para crear una instancia del autenticador llamando al constructor del autenticador en el método Service.onCreate()
del servicio.
En el siguiente fragmento, se muestra cómo definir el Service
vinculado:
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(this) } /* * 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(this); } /* * 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(); } }
Cómo agregar el archivo de metadatos del autenticador
Para conectar el componente del adaptador de sincronización con el marco de trabajo, debes proporcionar metadatos que describan el componente. Estos metadatos declaran el tipo de cuenta que creaste para tu adaptador de sincronización y declaran los elementos de la interfaz de usuario que el sistema muestra si deseas que el tipo de cuenta sea visible para el usuario. Declara esos metadatos en un archivo XML almacenado en el directorio /res/xml/
del proyecto de la app.
Puedes nombrar el archivo como quieras, aunque generalmente se llama authenticator.xml
.
Ese archivo XML contiene un único elemento <account-authenticator>
que tiene los siguientes atributos:
-
android:accountType
-
El framework del adaptador de sincronización requiere que cada adaptador de sincronización tenga un tipo de cuenta, en forma de nombre de dominio. Utiliza el tipo de cuenta como parte de la identificación interna del adaptador de sincronización. Para los servidores que requieren acceso, se envía el tipo de cuenta, junto con una cuenta de usuario, al servidor como parte de las credenciales de acceso.
Si el servidor no requiere acceso, debes proporcionar un tipo de cuenta. Para el valor, usa un nombre de dominio sobre el que tengas control. Si bien el framework lo usará para administrar tu adaptador de sincronización, no se enviará el valor a tu servidor.
-
android:icon
-
Es un elemento que apunta a un recurso de un elemento de diseño que contiene un ícono. Si haces visible el adaptador de sincronización especificando el atributo
android:userVisible="true"
enres/xml/syncadapter.xml
, debes proporcionar este recurso de ícono. Aparece en la sección Cuentas de la app de configuración del sistema. -
android:smallIcon
-
Es un elemento que apunta a un recurso de un elemento de diseño que contiene una versión pequeña del ícono. Se puede usar este recurso en lugar de
android:icon
en la sección Cuentas de la app de configuración del sistema, según el tamaño de la pantalla. -
android:label
-
Es una string localizable que identifica el tipo de cuenta de los usuarios. Si haces que el adaptador de sincronización sea visible especificando el atributo
android:userVisible="true"
enres/xml/syncadapter.xml
, debes proporcionar esta string. Aparece en la sección Cuentas de la app de configuración del sistema, junto al ícono que definiste para el autenticador.
En el siguiente fragmento de código, se muestra el archivo XML del autenticador que creaste anteriormente:
<?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"/>
Cómo declarar el autenticador en el manifiesto
En un paso anterior, creaste un Service
vinculado que conecta el autenticador con el framework del adaptador de sincronización. Para identificar este servicio en el sistema, debes declararlo en el manifiesto de la app agregando el siguiente elemento <service>
como un elemento secundario de <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>
El elemento <intent-filter>
configura un filtro que se activa mediante la acción del intent android.accounts.AccountAuthenticator
, que envía el sistema para ejecutar el autenticador. Cuando se activa el filtro, el sistema inicia AuthenticatorService
, el Service
vinculado que proporcionaste para unir el autenticador.
El elemento <meta-data>
declara los metadatos para el autenticador. El atributo android:name
vincula los metadatos al framework de autenticación. El elemento android:resource
especifica el nombre del archivo de metadatos del autenticador que creaste anteriormente.
Además de un autenticador, el adaptador de sincronización también requiere un proveedor de contenido. Si tu app aún no utiliza un proveedor de contenido, ve a la siguiente lección para obtener información sobre cómo crear un proveedor de contenido de stub; de lo contrario, consulta Cómo crear un adaptador de sincronización.