Tạo loại tài khoản tuỳ chỉnh

Cho đến nay, chúng ta đã nói về cách truy cập các API của Google. Các API này sử dụng tài khoản và người dùng do Google xác định. Tuy nhiên, nếu bạn có dịch vụ trực tuyến của riêng mình, dịch vụ đó sẽ không có tài khoản Google hoặc người dùng, bạn sẽ làm gì? Việc cài đặt các loại tài khoản mới trên thiết bị của người dùng tương đối đơn giản. Bài học này giải thích cách tạo loại tài khoản tuỳ chỉnh hoạt động tương tự như các tài khoản tích hợp sẵn.

Triển khai mã tài khoản tuỳ chỉnh của bạn

Điều đầu tiên bạn cần là cách để có được thông tin đăng nhập từ người dùng. Việc này có thể đơn giản như một hộp thoại yêu cầu nhập tên và mật khẩu. Hoặc đó có thể là một thủ thuật kỳ lạ hơn, chẳng hạn như mật khẩu một lần hoặc quét sinh trắc học. Dù bằng cách nào, bạn vẫn có trách nhiệm triển khai mã:

  1. Thu thập thông tin xác thực từ người dùng
  2. Xác thực thông tin đăng nhập với máy chủ
  3. Lưu trữ thông tin đăng nhập trên thiết bị

Thông thường, cả ba yêu cầu này đều có thể được xử lý bằng một hoạt động. Chúng tôi gọi đây là hoạt động xác thực.

Vì cần tương tác với hệ thống AccountManager, nên các hoạt động xác thực có một số yêu cầu nhất định mà các hoạt động thông thường không có. Để dễ dàng xác định mọi vấn đề, khung Android cung cấp một lớp cơ sở (AccountAuthenticatorActivity) mà bạn có thể mở rộng để tạo trình xác thực tuỳ chỉnh của riêng mình.

Việc bạn giải quyết hai yêu cầu đầu tiên của hoạt động xác thực, thu thập thông tin xác thực và xác thực như thế nào là hoàn toàn tuỳ thuộc vào bạn. (Nếu chỉ có một cách để thực hiện việc này, thì bạn không cần phải có các loại tài khoản "tuỳ chỉnh".) Yêu cầu thứ ba có cách triển khai chính tắc và khá đơn giản:

Kotlin

Account(username, your_account_type).also { account ->
    accountManager.addAccountExplicitly(account, password, null)
}

Java

final Account account = new Account(username, your_account_type);
accountManager.addAccountExplicitly(account, password, null);

Hãy thông minh về bảo mật!

Điều quan trọng bạn cần hiểu là AccountManager không phải là một dịch vụ mã hoá hay chuỗi khoá. Lớp này lưu trữ thông tin đăng nhập tài khoản ngay khi bạn truyền thông tin đó, dưới dạng văn bản thuần tuý. Trên hầu hết các thiết bị, đây không phải là vấn đề đặc biệt vì lưu trữ các thông tin này trong một cơ sở dữ liệu chỉ có thể truy cập để can thiệp vào hệ thống. Tuy nhiên, trên thiết bị bị can thiệp hệ thống, bất kỳ ai có quyền truy cập adb vào thiết bị đều có thể đọc được thông tin đăng nhập.

Vì vậy, bạn không nên truyền mật khẩu thực tế của người dùng đến AccountManager.addAccountExplicitly(). Thay vào đó, bạn nên lưu trữ một mã thông báo được mã hoá bảo mật, mã này chỉ được sử dụng hạn chế cho kẻ tấn công. Nếu thông tin đăng nhập của người dùng đang bảo vệ những nội dung có giá trị, bạn nên thận trọng cân nhắc thực hiện những việc tương tự.

Lưu ý: Đối với mã bảo mật, hãy làm theo quy tắc "Phim bí ẩn": đừng thử cách này tại nhà! Hãy tham khảo ý kiến của chuyên gia bảo mật trước khi triển khai bất kỳ mã tài khoản tuỳ chỉnh nào.

Giờ đây, tuyên bố từ chối trách nhiệm về bảo mật đã hết hiệu lực, đã đến lúc quay trở lại làm việc. Bạn đã triển khai phần thịt của mã tài khoản tuỳ chỉnh; công việc còn lại là hệ thống ống nước.

Mở rộng AbstractAccountAuthenticator

Để AccountManager hoạt động với mã tài khoản tuỳ chỉnh, bạn cần có một lớp triển khai các giao diện mà AccountManager mong đợi. Lớp này là lớp trình xác thực.

Cách dễ nhất để tạo một lớp trình xác thực là mở rộng AbstractAccountAuthenticator và triển khai các phương thức trừu tượng của lớp đó. Nếu bạn đã tìm hiểu các bài học trước, các phương thức trừu tượng của AbstractAccountAuthenticator sẽ trông quen thuộc: đây là phía ngược lại với các phương thức bạn đã gọi trong bài học trước để lấy thông tin tài khoản và mã thông báo uỷ quyền.

Việc triển khai một lớp trình xác thực đúng cách đòi hỏi một số đoạn mã riêng biệt. Trước tiên, AbstractAccountAuthenticator có 7 phương thức trừu tượng mà bạn phải ghi đè. Tiếp theo, bạn cần thêm bộ lọc ý định cho "android.accounts.AccountAuthenticator" vào tệp kê khai ứng dụng (như trong phần tiếp theo). Cuối cùng, bạn phải cung cấp 2 tài nguyên XML để xác định tên loại tài khoản tuỳ chỉnh và biểu tượng mà hệ thống sẽ hiển thị bên cạnh tài khoản thuộc loại này, cùng với các nội dung khác.

Bạn có thể tìm hướng dẫn từng bước để triển khai lớp xác thực thành công và các tệp XML trong tài liệu AbstractAccountAuthenticator.

Nếu hoạt động của trình xác thực cần bất kỳ tham số khởi chạy đặc biệt nào, bạn có thể đính kèm các tham số đó vào ý định bằng cách sử dụng Intent.putExtra().

Tạo dịch vụ xác thực

Giờ đây, khi đã có lớp trình xác thực, bạn cần một nơi để lưu trữ lớp đó. Trình xác thực tài khoản cần được cung cấp cho nhiều ứng dụng và hoạt động ở chế độ nền nên dĩ nhiên là các trình xác thực này phải chạy trong Service. Chúng tôi sẽ gọi đây là dịch vụ xác thực.

Dịch vụ xác thực của bạn có thể rất đơn giản. Bạn chỉ cần tạo một thực thể của lớp trình xác thực trong onCreate() và gọi getIBinder() trong onBind().

Đừng quên thêm thẻ <service> vào tệp kê khai và thêm bộ lọc ý định cho ý định AccountAuthenticator và khai báo trình xác thực tài khoản:

<service ...>
   <intent-filter>
      <action android:name="android.accounts.AccountAuthenticator" />
   </intent-filter>
   <meta-data android:name="android.accounts.AccountAuthenticator"
             android:resource="@xml/authenticator" />
</service>

Phân phối dịch vụ

Bạn đã hoàn tất! Giờ đây, hệ thống có thể nhận ra loại tài khoản của bạn, ngay bên cạnh tất cả các loại tài khoản có tên tuổi lớn như "Google" và "Doanh nghiệp". Bạn có thể sử dụng trang Cài đặt Tài khoản và đồng bộ hoá để thêm tài khoản và các ứng dụng yêu cầu tài khoản thuộc loại tuỳ chỉnh của bạn sẽ có thể liệt kê và xác thực giống như mọi loại tài khoản khác.

Tất nhiên, tất cả điều này giả định rằng dịch vụ tài khoản của bạn thực sự được cài đặt trên thiết bị. Nếu chỉ một ứng dụng có thể truy cập dịch vụ, thì đây không phải là vấn đề lớn — chỉ cần gói dịch vụ đó trong ứng dụng. Nhưng nếu bạn muốn nhiều ứng dụng dùng dịch vụ tài khoản của mình, thì mọi việc sẽ trở nên phức tạp hơn. Bạn không nên nhóm dịch vụ này với tất cả ứng dụng và có nhiều bản sao của dịch vụ đó mà lại chiếm dung lượng trên thiết bị của người dùng.

Một giải pháp là đặt dịch vụ trong một tệp APK nhỏ, chuyên dụng. Khi muốn sử dụng loại tài khoản tuỳ chỉnh của bạn, một ứng dụng có thể kiểm tra thiết bị để xem dịch vụ tài khoản tuỳ chỉnh của bạn có dùng được hay không. Nếu không, ứng dụng có thể chuyển hướng người dùng đến Google Play để tải dịch vụ xuống. Việc này thoạt nhìn có vẻ sẽ gây nhiều rắc rối, nhưng so với phương án thay thế việc nhập lại thông tin đăng nhập cho mọi ứng dụng sử dụng tài khoản tuỳ chỉnh thì việc này khá dễ dàng.