スタブ認証システムを作成する

同期アダプター フレームワークでは、同期アダプターが、アカウントに関連付けられているデバイス ストレージと、ログイン アクセスを必要とするサーバー ストレージとの間でデータを転送することを前提としています。このため、フレームワークでは、同期アダプターの一部として認証システムと呼ばれるコンポーネントを提供することが求められます。このコンポーネントは Android アカウントと認証フレームワークに接続し、ログイン情報などのユーザー認証情報を処理するための標準インターフェースを提供します。

アプリでアカウントを使用していない場合でも、認証システムコンポーネントを提供する必要があります。アカウントやサーバー ログインを使用しない場合は、認証システムによって処理される情報は無視されるため、スタブメソッドの実装を含む認証システムコンポーネントを指定できます。同期アダプター フレームワークが認証システムのメソッドを呼び出せるように、バインドされた Service を指定する必要もあります。

このレッスンでは、同期アダプター フレームワークの要件を満たす必要があるスタブ認証システムのすべての部分を定義する方法について説明します。ユーザー アカウントを処理する実際の認証システムを用意する必要がある場合は、AbstractAccountAuthenticator のリファレンス ドキュメントをご覧ください。

スタブ認証システム コンポーネントを追加する

スタブ認証システム コンポーネントをアプリに追加するには、AbstractAccountAuthenticator を拡張するクラスを作成してから、null を返すか、例外をスローして、必要なメソッドをスタブ化します。

次のスニペットは、スタブ認証システムクラスの例を示しています。

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

認証システムをフレームワークにバインドする

同期アダプター フレームワークが認証システムにアクセスするには、バインドされた Service を作成する必要があります。このサービスは、フレームワークが認証システムを呼び出して、認証システムとフレームワークの間でデータを渡せるようにする Android バインダ オブジェクトを提供します。

次のスニペットは、バインドされた 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();
    }
}

認証システム メタデータ ファイルを追加する

認証システム コンポーネントを同期アダプター フレームワークとアカウント フレームワークに接続するには、コンポーネントを記述するメタデータをこれらのフレームワークに提供する必要があります。このメタデータは、同期アダプター用に作成したアカウント タイプを宣言し、アカウント タイプをユーザーに表示する場合にシステムが表示するユーザー インターフェース要素を宣言します。このメタデータは、アプリ プロジェクトの /res/xml/ ディレクトリに保存されている XML ファイルで宣言します。 ファイルには任意の名前を付けることができますが、通常は authenticator.xml と呼ばれます。

この XML ファイルには、次の属性を持つ単一の要素 <account-authenticator> が含まれています。

android:accountType
同期アダプター フレームワークでは、各同期アダプターがアカウント タイプ(ドメイン名の形式)を持つ必要があります。フレームワークは、同期アダプターの内部識別情報の一部としてアカウント タイプを使用します。ログインが必要なサーバーの場合、アカウント タイプとユーザー アカウントがログイン認証情報の一部としてサーバーに送信されます。

ログインが不要なサーバーについても、アカウント タイプを指定する必要があります。値には、管理するドメイン名を使用します。フレームワークはこれを使用して同期アダプターを管理しますが、値はサーバーに送信されません。

android:icon
アイコンを含むドローアブル リソースのポインタ。res/xml/syncadapter.xml で属性 android:userVisible="true" を指定して同期アダプターを表示する場合は、このアイコン リソースを指定する必要があります。システムの設定アプリの [アカウント] セクションに表示されます。
android:smallIcon
小さいバージョンのアイコンを含むドローアブル リソースのポインタ。このリソースは、画面サイズによっては、システムの設定アプリの [アカウント] セクションで android:icon の代わりに使用できます。
android:label
ユーザーがアカウント タイプを識別するためのローカライズ可能な文字列。res/xml/syncadapter.xml で属性 android:userVisible="true" を指定して同期アダプターを表示する場合は、この文字列を指定する必要があります。これは、システムの設定アプリの [アカウント] セクションで、認証システム用に定義したアイコンの横にあるものです。

次のスニペットは、前に作成した認証システムの 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 要素には、前に作成した認証システムのメタデータ ファイルの名前を指定します。

認証システムに加えて、同期アダプターにはコンテンツ プロバイダが必要です。アプリでコンテンツ プロバイダをまだ使用していない場合は、次のレッスンに進んでスタブ コンテンツ プロバイダの作成方法を確認してください。使用していない場合は、同期アダプターの作成に進んでください。