Tạo trình xác thực mã giả lập

Khung bộ điều hợp đồng bộ hoá giả định rằng bộ điều hợp đồng bộ hoá chuyển dữ liệu giữa bộ nhớ thiết bị liên kết với bộ nhớ của tài khoản và bộ nhớ máy chủ yêu cầu quyền đăng nhập. Vì lý do này, khung dự kiến bạn sẽ cung cấp một thành phần có tên là trình xác thực như một phần của bộ điều hợp đồng bộ hoá. Thành phần này cắm vào khung xác thực và tài khoản Android, đồng thời cung cấp một giao diện chuẩn để xử lý thông tin xác thực của người dùng, chẳng hạn như thông tin đăng nhập.

Ngay cả khi ứng dụng của bạn không sử dụng tài khoản, bạn vẫn cần cung cấp thành phần xác thực. Nếu bạn không sử dụng tài khoản hoặc thông tin đăng nhập vào máy chủ, thông tin do trình xác thực xử lý sẽ bị bỏ qua. Vì vậy, bạn có thể cung cấp một thành phần trình xác thực chứa các phương thức triển khai phương thức mã giả lập. Bạn cũng cần cung cấp một Service ràng buộc cho phép khung bộ điều hợp đồng bộ hoá gọi các phương thức của trình xác thực.

Bài học này sẽ hướng dẫn bạn cách xác định tất cả các phần của trình xác thực mã giả lập mà bạn cần để đáp ứng các yêu cầu của khung bộ điều hợp đồng bộ hoá. Nếu bạn cần cung cấp một trình xác thực thực giúp xử lý tài khoản người dùng, hãy đọc tài liệu tham khảo về AbstractAccountAuthenticator.

Thêm thành phần trình xác thực mã giả lập

Để thêm thành phần trình xác thực mã giả lập vào ứng dụng của bạn, hãy tạo một lớp mở rộng AbstractAccountAuthenticator, sau đó mã hoá các phương thức bắt buộc, bằng cách trả về null hoặc gửi một ngoại lệ.

Đoạn mã sau đây cho thấy ví dụ về một lớp trình xác thực mã giả lập:

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

Liên kết trình xác thực với khung

Để khung bộ điều hợp đồng bộ hoá truy cập được vào trình xác thực, bạn phải tạo một Dịch vụ ràng buộc cho trình xác thực đó. Dịch vụ này cung cấp một đối tượng liên kết Android cho phép khung gọi trình xác thực và truyền dữ liệu giữa trình xác thực và khung.

Đoạn mã sau đây cho bạn biết cách xác định ràng buộc 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();
    }
}

Thêm tệp siêu dữ liệu của Authenticator

Để cắm thành phần trình xác thực vào bộ điều hợp đồng bộ hoá và khung tài khoản, bạn cần cung cấp cho khung này siêu dữ liệu mô tả thành phần đó. Siêu dữ liệu này khai báo loại tài khoản bạn đã tạo cho bộ điều hợp đồng bộ hoá và khai báo các phần tử giao diện người dùng mà hệ thống hiển thị nếu bạn muốn người dùng nhìn thấy loại tài khoản của mình. Khai báo siêu dữ liệu này trong tệp XML lưu trữ trong thư mục /res/xml/ của dự án ứng dụng. Bạn có thể đặt tên bất kỳ cho tệp, mặc dù tên thường là authenticator.xml.

Tệp XML này chứa một phần tử <account-authenticator> duy nhất có các thuộc tính sau:

android:accountType
Khung bộ điều hợp đồng bộ hoá yêu cầu mỗi bộ điều hợp đồng bộ hoá phải có một loại tài khoản, ở dạng tên miền. Khung này sử dụng loại tài khoản như một phần của thông tin nhận dạng nội bộ của bộ điều hợp đồng bộ hoá. Đối với các máy chủ yêu cầu đăng nhập, loại tài khoản cùng với tài khoản người dùng sẽ được gửi đến máy chủ dưới dạng một phần của thông tin đăng nhập.

Nếu máy chủ của bạn không yêu cầu đăng nhập, bạn vẫn phải cung cấp một loại tài khoản. Đối với giá trị này, hãy sử dụng tên miền mà bạn kiểm soát. Mặc dù khung sử dụng giá trị này để quản lý bộ điều hợp đồng bộ hoá, nhưng giá trị này không được gửi đến máy chủ của bạn.

android:icon
Con trỏ đến tài nguyên Có thể vẽ chứa biểu tượng. Nếu hiển thị bộ điều hợp đồng bộ hoá bằng cách chỉ định thuộc tính android:userVisible="true" trong res/xml/syncadapter.xml, thì bạn phải cung cấp tài nguyên biểu tượng này. Tài khoản này xuất hiện trong mục Accounts (Tài khoản) trong ứng dụng Cài đặt của hệ thống.
android:smallIcon
Con trỏ đến một tài nguyên có thể vẽ chứa một phiên bản nhỏ của biểu tượng. Bạn có thể sử dụng tài nguyên này thay cho android:icon trong phần Accounts (Tài khoản) của ứng dụng Cài đặt của hệ thống, tuỳ thuộc vào kích thước màn hình.
android:label
Chuỗi có thể bản địa hoá xác định loại tài khoản cho người dùng. Nếu hiển thị bộ điều hợp đồng bộ hoá bằng cách chỉ định thuộc tính android:userVisible="true" trong res/xml/syncadapter.xml, thì bạn nên cung cấp chuỗi này. Mã này xuất hiện trong phần Tài khoản của ứng dụng Cài đặt của hệ thống, bên cạnh biểu tượng mà bạn xác định cho trình xác thực.

Đoạn mã sau đây hiển thị tệp XML cho trình xác thực mà bạn đã tạo trước đây:

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

Khai báo trình xác thực trong tệp kê khai

Ở bước trước, bạn đã tạo một Service ràng buộc để liên kết trình xác thực với khung bộ điều hợp đồng bộ hoá. Để xác định dịch vụ này cho hệ thống, hãy khai báo dịch vụ trong tệp kê khai ứng dụng bằng cách thêm phần tử <service> sau đây làm phần tử con của <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>

Phần tử <intent-filter> thiết lập một bộ lọc được kích hoạt bởi thao tác theo ý định android.accounts.AccountAuthenticator do hệ thống gửi để chạy trình xác thực. Khi bộ lọc được kích hoạt, hệ thống sẽ khởi động AuthenticatorService, Service ràng buộc mà bạn đã cung cấp để bao bọc trình xác thực.

Phần tử <meta-data> khai báo siêu dữ liệu cho trình xác thực. Thuộc tính android:name liên kết siêu dữ liệu với khung xác thực. Phần tử android:resource chỉ định tên của tệp siêu dữ liệu trình xác thực mà bạn đã tạo trước đó.

Ngoài trình xác thực, bộ điều hợp đồng bộ hoá cũng yêu cầu nhà cung cấp nội dung. Nếu ứng dụng của bạn chưa sử dụng trình cung cấp nội dung, hãy chuyển sang bài học tiếp theo để tìm hiểu cách tạo trình cung cấp nội dung giả lập; nếu không, hãy chuyển đến bài học Tạo bộ điều hợp đồng bộ hoá.