Membuat authenticator stub

Framework adaptor sinkronisasi mengasumsikan bahwa adaptor sinkronisasi Anda mentransfer data antar penyimpanan perangkat yang terkait dengan akun dan penyimpanan server yang membutuhkan akses {i>login<i}. Karena alasan ini, kerangka kerja ini mengharapkan Anda menyediakan komponen yang disebut otentikator, sebagai bagian dari {i>adaptor<i}. Komponen ini terhubung ke akun Android dan kerangka kerja otentikasi dan menyediakan antarmuka standar untuk menangani kredensial pengguna seperti informasi login.

Meskipun aplikasi Anda tidak menggunakan akun, komponen authenticator harus tetap Anda sediakan. Jika Anda tidak menggunakan {i>login<i} akun atau server, informasi yang ditangani oleh otentikator diabaikan, sehingga Anda dapat menyediakan komponen otentikator yang berisi metode stub implementasi yang tepat. Anda juga perlu menyediakan Service terikat yang memungkinkan framework adaptor sinkronisasi untuk memanggil metode otentikator.

Pelajaran ini menunjukkan kepada Anda cara mendefinisikan semua bagian dari otentikator stub yang perlu memenuhi persyaratan framework adaptor sinkronisasi. Jika Anda perlu memberikan otentikator yang menangani akun pengguna, baca dokumentasi referensi untuk AbstractAccountAuthenticator.

Menambahkan komponen pengautentikasi stub

Untuk menambahkan komponen pengautentikasi stub ke aplikasi Anda, buat class yang memperluas AbstractAccountAuthenticator, lalu menghentikan metode yang diperlukan, dengan menampilkan null atau dengan menampilkan pengecualian.

Cuplikan berikut menunjukkan contoh class authenticator 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();
    }
}

Mengaitkan authenticator ke framework

Agar framework adaptor sinkronisasi dapat mengakses pengautentikasi, Anda harus membuat Layanan untuk perangkat tersebut. Layanan ini menyediakan objek binder Android yang memungkinkan framework untuk memanggil otentikator dan meneruskan data antara otentikator dan framework.

Cuplikan berikut menunjukkan cara menentukan Service terikat:

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

Menambahkan file metadata authenticator

Untuk menyambungkan komponen pengautentikasi Anda ke adaptor sinkronisasi dan framework akun, menyediakan {i>framework<i} dengan metadata yang menjelaskan komponen. Metadata ini mendeklarasikan jenis akun yang telah Anda buat untuk adaptor sinkronisasi dan mendeklarasikan elemen antarmuka pengguna yang ditampilkan sistem jika Anda ingin membuat jenis akun Anda terlihat oleh pengguna. Deklarasikan ini metadata dalam file XML yang disimpan di direktori /res/xml/ di project aplikasi Anda. Anda dapat memberikan nama apa pun pada file tersebut, meskipun biasanya disebut authenticator.xml.

File XML ini berisi satu elemen <account-authenticator> yang memiliki atribut berikut:

android:accountType
Framework adaptor sinkronisasi mengharuskan setiap adaptor sinkronisasi memiliki tipe akun, dalam bentuk dari nama domain. Kerangka kerja ini menggunakan tipe akun sebagai bagian dari metode identifikasi internal. Untuk server yang memerlukan {i>login<i}, tipe akun bersama dengan akun pengguna dikirim ke server sebagai bagian dari kredensial {i>login<i}.

Jika server tidak memerlukan login, Anda tetap harus menyediakan jenis akun. Untuk gunakan nama domain yang Anda kontrol. Sementara kerangka kerja menggunakannya untuk mengelola adaptor sinkronisasi, nilainya tidak dikirim ke server Anda.

android:icon
Pointer ke Drawable resource yang berisi ikon. Jika Anda membuat adaptor sinkronisasi terlihat dengan menetapkan atribut android:userVisible="true" dalam res/xml/syncadapter.xml, maka Anda harus menyediakan resource ikon ini. Kolom ini muncul di bagian Akun aplikasi Settings di sistem.
android:smallIcon
Pointer ke Drawable resource yang berisi ikon versi kecil. Sumber daya ini dapat digunakan sebagai pengganti android:icon di bagian Akun di aplikasi Setelan sistem, sesuai dengan ukuran layar.
android:label
String yang dapat dilokalkan yang mengidentifikasi jenis akun kepada pengguna. Jika Anda membuat adaptor sinkronisasi terlihat dengan menetapkan atribut android:userVisible="true" di res/xml/syncadapter.xml, maka Anda harus menyediakan string ini. ID tersebut muncul dalam Bagian Akun di aplikasi Setelan sistem, di samping ikon yang Anda tentukan untuk pengautentikasi Anda.

Cuplikan berikut menunjukkan file XML untuk authenticator yang Anda buat sebelumnya:

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

Mendeklarasikan pengautentikasi dalam manifes

Pada langkah sebelumnya, Anda membuat Service terikat yang menautkan pengautentikasi ke kerangka kerja adaptor sinkronisasi. Untuk mengidentifikasi layanan ini ke sistem, deklarasikan di aplikasi Anda dengan menambahkan <service> sebagai elemen turunan dari <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>

Tujuan <intent-filter> akan menyiapkan filter yang dipicu oleh tindakan intent android.accounts.AccountAuthenticator, yang dikirim oleh sistem untuk menjalankan pengautentikasi Anda. Saat filter dipicu, sistem akan memulai AuthenticatorService, Service terikat yang telah Anda berikan untuk menggabungkan pengautentikasi.

Tujuan <meta-data> mendeklarasikan metadata untuk otentikator. Tujuan android:name menautkan meta-data ke kerangka kerja otentikasi. Tujuan android:resource menetapkan nama file metadata otentikator yang Anda buat sebelumnya.

Selain pengautentikasi, adaptor sinkronisasi juga memerlukan penyedia konten. Jika aplikasi Anda tidak menggunakan penyedia konten. Buka pelajaran berikutnya untuk mempelajari cara membuat konten stub cloud Anda; jika tidak, buka tutorial Membuat Adaptor Sinkronisasi.