Создайте заглушку аутентификатора

Платформа адаптера синхронизации предполагает, что ваш адаптер синхронизации передает данные между хранилищем устройства, связанным с учетной записью, и хранилищем сервера, требующим доступа для входа в систему. По этой причине платформа ожидает, что вы предоставите компонент, называемый аутентификатором, как часть вашего адаптера синхронизации. Этот компонент подключается к учетным записям Android и системе аутентификации и предоставляет стандартный интерфейс для обработки учетных данных пользователя, таких как данные для входа.

Даже если ваше приложение не использует учетные записи, вам все равно необходимо предоставить компонент проверки подлинности. Если вы не используете учетные записи или вход на сервер, информация, обрабатываемая аутентификатором, игнорируется, поэтому вы можете предоставить компонент аутентификатора, содержащий реализации метода-заглушки. Вам также необходимо предоставить связанную Service , которая позволит платформе адаптера синхронизации вызывать методы аутентификатора.

В этом уроке показано, как определить все части заглушки аутентификатора, необходимые для удовлетворения требований платформы адаптера синхронизации. Если вам необходимо предоставить настоящий аутентификатор, который обрабатывает учетные записи пользователей, прочтите справочную документацию по AbstractAccountAuthenticator .

Добавьте компонент-заглушку аутентификатора

Чтобы добавить в приложение компонент-заглушку проверки подлинности, создайте класс, расширяющий AbstractAccountAuthenticator , а затем заглушите необходимые методы, либо вернув null , либо выдав исключение.

В следующем фрагменте показан пример класса-заглушки аутентификатора:

Котлин

/*
 * 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()
    }
}

Ява

/*
 * 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();
    }
}

Привязка аутентификатора к фреймворку

Чтобы платформа адаптера синхронизации могла получить доступ к вашему аутентификатору, необходимо создать для него привязанную службу. Эта служба предоставляет объект привязки Android, который позволяет платформе вызывать ваш аутентификатор и передавать данные между аутентификатором и платформой.

В следующем фрагменте показано, как определить привязанный Service :

Котлин

/**
* 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
}

Ява

/**
 * 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();
    }
}

Добавьте файл метаданных аутентификатора

Чтобы подключить компонент аутентификации к адаптеру синхронизации и платформам учетных записей, вам необходимо предоставить этой платформе метаданные, описывающие компонент. Эти метаданные объявляют тип учетной записи, созданный вами для адаптера синхронизации, и объявляют элементы пользовательского интерфейса, которые отображает система, если вы хотите, чтобы тип вашей учетной записи был виден пользователю. Объявите эти метаданные в XML-файле, хранящемся в каталоге /res/xml/ вашего проекта приложения. Вы можете дать файлу любое имя, хотя обычно он authenticator.xml .

Этот XML-файл содержит один элемент <account-authenticator> , который имеет следующие атрибуты:

android:accountType
Платформа адаптера синхронизации требует, чтобы каждый адаптер синхронизации имел тип учетной записи в виде имени домена. Платформа использует тип учетной записи как часть внутренней идентификации адаптера синхронизации. Для серверов, требующих входа в систему, тип учетной записи вместе с учетной записью пользователя отправляется на сервер как часть учетных данных для входа.

Если ваш сервер не требует входа в систему, вам все равно придется указать тип учетной записи. В качестве значения используйте доменное имя, которым вы управляете. Хотя платформа использует его для управления адаптером синхронизации, значение не отправляется на ваш сервер.

android:icon
Указатель на ресурс Drawable , содержащий значок. Если вы сделаете адаптер синхронизации видимым, указав атрибут android:userVisible="true" в res/xml/syncadapter.xml , вам необходимо предоставить этот ресурс значка. Он отображается в разделе «Учетные записи» приложения «Настройки системы».
android:smallIcon
Указатель на ресурс Drawable , содержащий уменьшенную версию значка. Этот ресурс можно использовать вместо android:icon в разделе «Учетные записи» приложения «Настройки системы», в зависимости от размера экрана.
android:label
Локализуемая строка, которая идентифицирует тип учетной записи для пользователей. Если вы сделаете адаптер синхронизации видимым, указав атрибут android:userVisible="true" в res/xml/syncadapter.xml , вам следует указать эту строку. Он отображается в разделе «Учетные записи» приложения «Настройки системы» рядом со значком, который вы определяете для аутентификатора.

В следующем фрагменте показан XML-файл для созданного вами ранее аутентификатора:

<?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"/>

Объявить аутентификатор в манифесте

На предыдущем шаге вы создали связанную Service , которая связывает аутентификатор с платформой адаптера синхронизации. Чтобы идентифицировать эту службу для системы, объявите ее в манифесте вашего приложения, добавив следующий элемент <service> в качестве дочернего элемента <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>

Элемент <intent-filter> устанавливает фильтр, который активируется действием намерения android.accounts.AccountAuthenticator , которое отправляется системой для запуска аутентификатора. Когда фильтр срабатывает, система запускает AuthenticatorService — привязанную Service , которую вы предоставили для оболочки аутентификатора.

Элемент <meta-data> объявляет метаданные для аутентификатора. Атрибут android:name связывает метаданные со структурой аутентификации. Элемент android:resource указывает имя файла метаданных аутентификатора, который вы создали ранее.

Помимо аутентификатора, адаптеру синхронизации также требуется поставщик контента. Если ваше приложение еще не использует поставщика контента, перейдите к следующему уроку, чтобы узнать, как создать поставщика контента-заглушки; в противном случае перейдите к уроку Создание адаптера синхронизации .