Tối ưu hoá ứng dụng để tự động điền

Các ứng dụng sử dụng khung hiển thị chuẩn hoạt động với khung tự động điền mà không cần phải có cấu hình đặc biệt. Tuy nhiên, bạn có thể tối ưu hoá cách ứng dụng sử dụng khung.

Thiết lập môi trường tự động điền

Phần này mô tả cách thiết lập chức năng tự động điền cơ bản cho ứng dụng.

Định cấu hình dịch vụ tự động điền

Bạn phải định cấu hình dịch vụ tự động điền trên thiết bị để ứng dụng có thể sử dụng khung tự động điền. Tuy hầu hết điện thoại và máy tính bảng chạy Android 8.0 (API cấp 26) trở lên có dịch vụ tự động điền, nhưng bạn nên sử dụng dịch vụ kiểm thử khi kiểm thử ứng dụng, chẳng hạn như dịch vụ tự động điền trong mẫu khung tự động điền Java | Kotlin của Android. Khi sử dụng trình mô phỏng, bạn phải đặt rõ ràng dịch vụ tự động điền vì trình mô phỏng có thể không có sẵn dịch vụ mặc định.

Sau khi bạn đã cài đặt dịch vụ tự động điền kiểm thử qua ứng dụng mẫu, hãy bật dịch vụ tự động điền bằng cách chuyển đến phần Settings (Cài đặt) > System (Hệ thống) > Languages & input (Ngôn ngữ và nhập liệu) > Advanced (Nâng cao) > Input assistance (Hỗ trợ nhập liệu) > Autofill service (Dịch vụ tự động điền).

Để biết thêm thông tin về cách định cấu hình trình mô phỏng để kiểm thử tính năng tự động điền, hãy xem nội dung Kiểm thử tính năng tự động điền trong ứng dụng.

Đưa ra gợi ý để tự động điền

Dịch vụ tự động điền sử dụng phương pháp phỏng đoán để cố gắng xác định loại của mỗi thành phần hiển thị (view). Tuy nhiên, nếu ứng dụng của bạn dựa vào thông tin phỏng đoán này, thì hành vi tự động điền có thể đột ngột thay đổi khi bạn cập nhật ứng dụng. Để đảm bảo dịch vụ tự động điền xác định chính xác hệ số hình dạng của ứng dụng, bạn nên đưa ra gợi ý tự động điền (autofill hint).

Bạn có thể đặt các gợi ý (hint) này bằng cách sử dụng thuộc tính android:autofillHints. Ví dụ sau đây gợi ý một "mật khẩu" cho một EditText:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:autofillHints="password" />

Bạn cũng có thể đặt gợi ý theo phương thức lập trình bằng cách sử dụng setAutofillHints() như trình bày trong ví dụ sau:

Kotlin

val password = findViewById<EditText>(R.id.password)
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)

Java

EditText password = findViewById(R.id.password);
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);

Hằng số gợi ý xác định trước

Khung tự động điền không xác thực các gợi ý; các gợi ý được chuyển nhưng không có thay đổi hoặc xác thực nào đối với dịch vụ tự động điền. Mặc dù bạn có thể sử dụng giá trị bất kỳ, lớp View và lớp AndroidX HintConstants chứa danh sách hằng số gợi ý được hỗ trợ chính thức.

Khi kết hợp các hằng số này, bạn có thể tạo bố cục cho các trường hợp tự động điền phổ biến:

Thông tin đăng nhập vào tài khoản

Khi hệ thống tự động điền thông tin đăng nhập vào tài khoản, biểu mẫu đăng nhập có thể chứa các gợi ý như AUTOFILL_HINT_USERNAMEAUTOFILL_HINT_PASSWORD.

Khi tạo tài khoản mới hoặc khi người dùng thay đổi tên người dùng và mật khẩu, bạn có thể sử dụng AUTOFILL_HINT_NEW_USERNAMEAUTOFILL_HINT_NEW_PASSWORD.

Thông tin thẻ tín dụng

Khi yêu cầu thông tin thẻ tín dụng, bạn có thể sử dụng các gợi ý như AUTOFILL_HINT_CREDIT_CARD_NUMBERAUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE.

Đối với ngày hết hạn thẻ tín dụng, hãy thực hiện một trong các gợi ý sau:

Địa chỉ thực tế

Khi tự động điền địa chỉ thực tế, bạn có thể sử dụng các gợi ý sau đây:

Tên người

Khi tự động điền tên người, bạn có thể sử dụng các gợi ý sau:

Số điện thoại

Đối với số điện thoại, bạn có thể sử dụng:

Mật khẩu một lần (OTP)

Đối với mật khẩu một lần trong một thành phần hiển thị, bạn có thể sử dụng AUTOFILL_HINT_SMS_OTP.

Khi sử dụng nhiều khung hiển thị, trong đó mỗi khung hiển thị liên kết với một chữ số duy nhất của OTP, bạn có thể sử dụng phương thức generateSmsOtpHintForCharacterPosition() để tạo gợi ý cho mỗi ký tự.

Đánh dấu các trường là quan trọng đối với tính năng tự động điền

Bạn có thể cho hệ thống biết liệu có đưa các trường riêng lẻ trong ứng dụng của bạn vào cấu trúc thành phần hiển thị cho mục đích tự động điền hay không. Theo mặc định, thành phần hiển thị này sử dụng chế độ IMPORTANT_FOR_AUTOFILL_AUTO cho phép Android sử dụng các phương pháp phỏng đoán để xác định xem thành phần hiển thị này có quan trọng đối với tính năng tự động điền hay không.

Bạn có thể đặt giá trị cho tầm quan trọng bằng cách sử dụng thuộc tính android:importantForAutofill:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:importantForAutofill="no" />

Giá trị của importantForAutofill có thể là giá trị bất kỳ được xác định trong android:importantForAutofill:

auto
Cho phép hệ thống Android sử dụng các phương pháp phỏng đoán để xác định xem thành phần hiển thị này có quan trọng đối với tính năng tự động điền hay không.
no
Thành phần hiển thị này không quan trọng đối với tính năng tự động điền.
noExcludeDescendants
Thành phần hiển thị này và các thành phần hiển thị con không quan trọng đối với tính năng tự động điền.
yes
Thành phần hiển thị này rất quan trọng đối với tính năng tự động điền.
yesExcludeDescendants
Thành phần hiển thị này rất quan trọng đối với tính năng tự động điền, nhưng các thành phần hiển thị con của thành phần hiển thị này không quan trọng đối với tính năng tự động điền.

Bạn cũng có thể sử dụng phương thức setImportantForAutofill():

Kotlin

val captcha = findViewById<TextView>(R.id.captcha)
captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)

Java

TextView captcha = findViewById(R.id.captcha);
captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);

Có trường hợp thành phần hiển thị (view), cấu trúc thành phần hiển thị (view structure) hoặc toàn bộ hoạt động (activity) không quan trọng đối với tính năng tự động điền:

  • Trường CAPTCHA trong hoạt động đăng nhập thường không quan trọng đối với tính năng tự động điền. Trong những trường hợp như thế, bạn có thể đánh dấu thành phần hiển thị là IMPORTANT_FOR_AUTOFILL_NO.
  • Trong một khung hiển thị nơi người dùng tạo nội dung, chẳng hạn như trình chỉnh sửa văn bản hoặc bảng tính, thì toàn bộ cấu trúc khung hiển thị thường không quan trọng đối với tính năng tự động điền. Trong những trường hợp như thế này, bạn có thể đánh dấu thành phần hiển thị đó là IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS để đảm bảo rằng tất cả thành phần con của chế độ xem đó cũng được đánh dấu là không quan trọng đối với tính năng tự động điền.
  • Đối với một số hoạt động trong trò chơi, chẳng hạn như các hoạt động thể hiện lối chơi, không có thành phần hiển thị nào trong số các hoạt động này là quan trọng đối với tính năng tự động điền. Bạn có thể đánh dấu thành phần hiển thị gốc là IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS để đảm bảo tất cả thành phần hiển thị trong hoạt động được đánh dấu là không quan trọng đối với tính năng tự động điền.

Liên kết dữ liệu ứng dụng di động với dữ liệu trang web

Các dịch vụ tự động điền như Tự động điền bằng Google (Autofill with Google) có thể chia sẻ dữ liệu đăng nhập của người dùng giữa các trình duyệt và thiết bị Android sau khi ứng dụng và trang web được liên kết. Khi người dùng chọn cùng một dịch vụ tự động điền trên cả hai nền tảng, thao tác đăng nhập vào ứng dụng web của bạn sẽ cung cấp thông tin đăng nhập để tự động điền khi họ đăng nhập vào ứng dụng Android tương ứng.

Để liên kết ứng dụng Android với trang web, bạn phải lưu trữ một Đường liên kết đến tài sản kỹ thuật số (Digital Asset Links) có liên quan đến delegate_permission/common.get_login_creds trên trang web. Sau đó, hãy khai báo mối liên kết này trong tệp AndroidManifest.xml của ứng dụng. Để biết hướng dẫn chi tiết về cách liên kết trang web với ứng dụng Android, hãy xem phần Bật tính năng tự động đăng nhập trên ứng dụng và trang web.

Hoàn tất quy trình tự động điền

Phần này mô tả các tình huống cụ thể mà bạn có thể từng bước cải thiện chức năng tự động điền cho người dùng ứng dụng.

Xác định xem bạn đã bật tính năng tự động điền hay chưa

Bạn có thể triển khai chức năng tự động điền bổ sung trong ứng dụng hoặc thậm chí trong các thành phần hiển thị cụ thể của ứng dụng nếu người dùng có thể sử dụng tính năng tự động điền. Ví dụ: TextView sẽ cho thấy một mục tự động điền trong trình đơn mục bổ sung nếu tính năng tự động điền được bật cho người dùng. Để kiểm tra xem tính năng tự động điền đã được bật cho người dùng hay chưa, hãy gọi phương thức isEnabled() của đối tượng AutofillManager.

Người dùng có thể bật hoặc tắt tính năng tự động điền cũng như thay đổi dịch vụ tự động điền bằng cách chuyển đến phần Settings (Cài đặt) > System (Hệ thống) > Languages & input (Ngôn ngữ và nhập liệu) > Advanced (Nâng cao) > Input assistance (Hỗ trợ nhập liệu) > Autofill service (Dịch vụ tự động điền). Ứng dụng không thể ghi đè các chế độ cài đặt tự động điền của người dùng.

Để đảm bảo người dùng có trải nghiệm đăng ký và đăng nhập tốt nhất mà không cần tự động điền, hãy cân nhắc triển khai Smart Lock cho Mật khẩu.

Buộc thực hiện yêu cầu tự động điền

Đôi khi, bạn có thể phải buộc thực hiện một yêu cầu tự động điền để phản hồi một hành động của người dùng. Ví dụ: TextView cung cấp một mục trong trình đơn tự động điền khi người dùng nhấn và giữ thành phần hiển thị. Mã ví dụ sau đây cho thấy cách buộc thực hiện một yêu cầu tự động điền:

Kotlin

fun eventHandler(view: View) {
    val afm = requireContext().getSystemService(AutofillManager::class.java)
    afm?.requestAutofill(view)
}

Java

public void eventHandler(View view) {
    AutofillManager afm = context.getSystemService(AutofillManager.class);
    if (afm != null) {
        afm.requestAutofill(view);
    }
}

Bạn cũng có thể sử dụng phương thức cancel() để huỷ ngữ cảnh tự động điền hiện tại. Cách này có thể hữu ích, chẳng hạn như nếu bạn có một nút xoá các trường trên trang đăng nhập.

Sử dụng đúng loại tự động điền cho dữ liệu trong trình điều khiển bộ chọn

Bộ chọn (picker) rất hữu ích trong một số trường hợp tự động điền, vì công cụ này mang đến một giao diện người dùng cho phép người dùng thay đổi giá trị của trường lưu trữ dữ liệu ngày hoặc giờ. Ví dụ: trong biểu mẫu thẻ tín dụng, bộ chọn ngày cho phép người dùng nhập hoặc thay đổi ngày hết hạn của thẻ tín dụng. Tuy nhiên, bạn phải sử dụng một thành phần hiển thị khác, chẳng hạn như EditText, để cho thấy dữ liệu khi bộ chọn không xuất hiện.

Đối tượng EditText vốn dự kiến sẽ có dữ liệu tự động điền thuộc loại AUTOFILL_TYPE_TEXT. Nếu đang sử dụng một loại dữ liệu khác, bạn nên tạo một thành phần hiển thị tuỳ chỉnh kế thừa từ EditText và triển khai các phương thức cần thiết để xử lý loại dữ liệu tương ứng. Ví dụ: nếu bạn có trường ngày, hãy triển khai các phương thức có logic xử lý chính xác các giá trị thuộc loại AUTOFILL_TYPE_DATE.

Khi bạn chỉ định loại dữ liệu tự động điền, dịch vụ tự động điền có thể tạo một bản trình bày phù hợp cho dữ liệu xuất hiện trong thành phần hiển thị. Để biết thêm thông tin, hãy xem phần Sử dụng tính năng tự động điền trong bộ chọn.

Hoàn tất ngữ cảnh tự động điền

Khung tự động điền sẽ lưu dữ liệu mà người dùng nhập vào để sử dụng sau này bằng cách đưa ra thông báo "Save for autofill?" ("Lưu để tự động điền?") sau khi ngữ cảnh tự động điền hoàn tất. Thường thì ngữ cảnh tự động điền sẽ hoàn tất khi một hoạt động kết thúc. Tuy nhiên, có một số tình huống bạn cần thông báo rõ ràng cho khung này; ví dụ: nếu bạn đang sử dụng cùng một hoạt động nhưng nhiều mảnh (fragment) cho cả màn hình đăng nhập và màn hình nội dung. Trong những trường hợp đặc biệt này, bạn có thể kết thúc ngữ cảnh một cách rõ ràng bằng cách gọi AutofillManager.commit().

Hỗ trợ thành phần hiển thị tuỳ chỉnh

Các thành phần hiển thị tuỳ chỉnh có thể chỉ định siêu dữ liệu xuất hiện cho khung tự động điền bằng cách sử dụng API tự động điền. Một số thành phần hiển thị hoạt động như một vùng chứa thành phần con ảo, chẳng hạn như các thành phần hiển thị chứa giao diện người dùng hiển thị OpenGL. Các thành phần hiển thị này phải sử dụng API để xác định cấu trúc của thông tin dùng trong ứng dụng trước khi có thể hoạt động với khung tự động điền.

Nếu ứng dụng của bạn sử dụng thành phần hiển thị tuỳ chỉnh, thì bạn phải xem xét các trường hợp sau:

  • Khung hiển thị tuỳ chỉnh có cấu trúc khung hiển thị chuẩn hay cấu trúc khung hiển thị mặc định.
  • Khung hiển thị tuỳ chỉnh có cấu trúc ảo hay cấu trúc khung hiển thị không có sẵn cho khung tự động điền.

Khung hiển thị tuỳ chỉnh có cấu trúc khung hiển thị chuẩn

Thành phần hiển thị tuỳ chỉnh có thể xác định siêu dữ liệu mà tính năng tự động điền cần có để hoạt động được. Bạn nên đảm bảo thành phần hiển thị tuỳ chỉnh quản lý siêu dữ liệu một cách phù hợp để dùng được khung tự động điền. Thành phần hiển thị tuỳ chỉnh của bạn sẽ thực hiện các hành động sau:

  • Xử lý giá trị tự động điền mà khung gửi đến ứng dụng.
  • Cung cấp loại và giá trị tự động điền cho khung.

Khi tính năng tự động điền được kích hoạt, khung tự động điền sẽ gọi autofill() trên khung hiển thị rồi gửi giá trị mà khung hiển thị sẽ sử dụng. Bạn nên triển khai autofill() để chỉ định cách thành phần hiển thị tuỳ chỉnh xử lý giá trị tự động điền.

Thành phần hiển thị của bạn cần chỉ định loại và giá trị tự động điền bằng cách ghi đè phương thức getAutofillType()getAutofillValue() tương ứng. Bằng cách thêm mã này, bạn đảm bảo khung hiển thị của mình có thể cung cấp các loại và giá trị tự động điền thích hợp cho khung.

Cuối cùng, tính năng tự động điền sẽ không điền vào khung hiển thị này nếu người dùng không cung cấp được giá trị cho khung hiển thị ở trạng thái hiện tại (ví dụ: nếu khung hiển thị bị tắt). Trong những trường hợp này, getAutofillType() sẽ trả về AUTOFILL_TYPE_NONE, getAutofillValue() sẽ trả về nullautofill() không làm gì.

Các trường hợp sau đây yêu cầu thêm một số bước để hoạt động chính xác trong khung:

  • Bạn có thể chỉnh sửa thành phần hiển thị tuỳ chỉnh.
  • Thành phần hiển thị tuỳ chỉnh chứa dữ liệu nhạy cảm.

Bạn có thể chỉnh sửa thành phần hiển thị tuỳ chỉnh

Nếu chỉnh sửa được thành phần hiển thị, bạn nên thông báo cho khung tự động điền về các thay đổi bằng cách gọi notifyValueChanged() trên đối tượng AutofillManager.

Thành phần hiển thị tuỳ chỉnh chứa dữ liệu nhạy cảm

Nếu khung hiển thị chứa thông tin nhận dạng cá nhân (PII) – chẳng hạn như địa chỉ email, số thẻ tín dụng và mật khẩu – thì khung hiển thị này sẽ được đánh dấu là chứa thông tin nhận dạng cá nhân. Nhìn chung, các thành phần hiển thị có nội dung được lấy từ các tài nguyên tĩnh thì không chứa dữ liệu nhạy cảm, nhưng các thành phần hiển thị có nội dung được đặt theo phương thức động thì có thể có. Ví dụ: nhãn chứa nội dung nhập tên người dùng của bạn không chứa dữ liệu nhạy cảm, trong khi nhãn chứa nội dung Xin chào, John có chứa dữ liệu nhạy cảm. Để đánh dấu thành phần hiển thị có chứa dữ liệu nhạy cảm (sensitive) hay không, hãy triển khai onProvideAutofillStructure() và gọi setDataIsSensitive() trên đối tượng ViewStructure.

Mã ví dụ sau đây cho thấy cách đánh dấu dữ liệu trong cấu trúc thành phần hiển thị là nhạy cảm hoặc không nhạy cảm:

Kotlin

override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) {
    super.onProvideAutofillStructure(structure, flags)

    // Content that comes from static resources generally isn't sensitive.
    val sensitive = !contentIsSetFromResources()
    structure.setDataIsSensitive(sensitive)
}

Java

@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
    super.onProvideAutofillStructure(structure, flags);

    // Content that comes from static resources generally isn't sensitive.
    boolean sensitive = !contentIsSetFromResources();
    structure.setDataIsSensitive(sensitive);
}

Nếu khung hiển thị chỉ chấp nhận những giá trị được xác định trước, bạn có thể sử dụng phương thức setAutofillOptions() để đặt các tuỳ chọn có thể dùng để tự động điền khung hiển thị này. Cụ thể, các khung hiển thị có loại tự động điền là AUTOFILL_TYPE_LIST sẽ sử dụng phương thức này vì dịch vụ tự động điền có thể hoạt động hiệu quả hơn nếu có sẵn các tuỳ chọn để điền vào khung hiển thị.

Các thành phần hiển thị sử dụng trình chuyển đổi (adapter), chẳng hạn như Spinner, cũng có cách hoạt động tương tự. Ví dụ: một trình đơn vòng quay (spinner) cung cấp các năm được tạo theo phương thức động (dựa trên năm hiện tại) để sử dụng trong các trường hết hạn của thẻ tín dụng có thể triển khai phương thức getAutofillOptions() của giao diện Adapter để cung cấp danh sách năm.

Các khung hiển thị sử dụng ArrayAdapter cũng có thể cung cấp danh sách giá trị. ArrayAdapter tự động đặt các tuỳ chọn tự động điền cho các tài nguyên tĩnh. Tuy nhiên, nếu cung cấp các giá trị động, bạn nên ghi đè getAutofillOptions().

Thành phần hiển thị tuỳ chỉnh mang cấu trúc ảo

Khung tự động điền cần có một cấu trúc thành phần hiển thị (view structure) trước khi có thể chỉnh sửa và lưu thông tin trong giao diện người dùng của ứng dụng. Có một số tình huống cấu trúc thành phần hiển thị không dùng được cho khung:

  • Ứng dụng sử dụng một công cụ kết xuất hình ảnh cấp thấp, chẳng hạn như OpenGL, để kết xuất giao diện người dùng.
  • Ứng dụng sử dụng một phiên bản của Canvas để vẽ giao diện người dùng.

Trong trường hợp này, bạn có thể chỉ định cấu trúc thành phần hiển thị bằng cách triển khai onProvideAutofillVirtualStructure() rồi làm theo các bước sau:

  1. Tăng số lượng con của cấu trúc thành phần hiển thị bằng cách gọi addChildCount().
  2. Thêm thành phần con bằng cách gọi newChild().
  3. Đặt mã nhận dạng tự động điền cho thành phần con bằng cách gọi setAutofillId().
  4. Đặt các thuộc tính có liên quan, chẳng hạn như loại và giá trị tự động điền.
  5. Nếu dữ liệu trong thành phần con ảo là nhạy cảm, thì bạn nên chuyển true đến setDataIsSensitive() hoặc false.

Đoạn mã sau đây cho biết cách tạo thành phần con mới trong cấu trúc ảo:

Kotlin

override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) {

    super.onProvideAutofillVirtualStructure(structure, flags)

    // Create a new child in the virtual structure.
    structure.addChildCount(1)
    val child = structure.newChild(childIndex)

    // Set the autofill ID for the child.
    child.setAutofillId(structure.autofillId!!, childVirtualId)

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue)
    child.setAutofillType(childAutofillType)

    // Some children can provide a list of values. For example, if the child is
    // a spinner.
    val childAutofillOptions = arrayOf<CharSequence>("option1", "option2")
    child.setAutofillOptions(childAutofillOptions)

    // Just like other types of views, mark the data as sensitive, if
    // appropriate.
    val sensitive = !contentIsSetFromResources()
    child.setDataIsSensitive(sensitive)
}

Java

@Override
public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {

    super.onProvideAutofillVirtualStructure(structure, flags);

    // Create a new child in the virtual structure.
    structure.addChildCount(1);
    ViewStructure child =
            structure.newChild(childIndex);

    // Set the autofill ID for the child.
    child.setAutofillId(structure.getAutofillId(), childVirtualId);

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue);
    child.setAutofillType(childAutofillType);

    // Some children can provide a list of values. For example, if the child is
    // a spinner.
    CharSequence childAutofillOptions[] = { "option1", "option2" };
    child.setAutofillOptions(childAutofillOptions);

    // Just like other types of views, mark the data as sensitive, if
    // appropriate.
    boolean sensitive = !contentIsSetFromResources();
    child.setDataIsSensitive(sensitive);
}

Khi các phần tử trong cấu trúc ảo (virtual structure) thay đổi, bạn nên thông báo cho khung bằng cách thực hiện các nhiệm vụ sau:

  • Nếu tiêu điểm bên trong thành phần con thay đổi, hãy gọi notifyViewEntered()notifyViewExited() trên đối tượng AutofillManager.
  • Nếu giá trị của thành phần con thay đổi, hãy gọi notifyValueChanged() trên đối tượng AutofillManager.
  • Nếu hệ phân cấp thành phần hiển thị không còn nữa vì người dùng đã hoàn tất một bước trong quy trình làm việc (chẳng hạn như, người dùng đã đăng nhập bằng biểu mẫu đăng nhập), hãy gọi commit() trên đối tượng AutofillManager.
  • Nếu hệ phân cấp khung hiển thị không còn hợp lệ vì người dùng đã huỷ một bước trong quy trình (ví dụ: nếu người dùng nhấp vào nút xoá biểu mẫu đăng nhập), hãy gọi cancel() trên đối tượng AutofillManager.

Sử dụng lệnh gọi lại trên sự kiện tự động điền

Nếu ứng dụng của bạn cung cấp khung hiển thị tự động hoàn thành riêng, bạn cần có một cơ chế để yêu cầu ứng dụng bật hoặc tắt các khung hiển thị đó nhằm phản hồi trước những thay đổi trong khả năng tự động điền trên giao diện người dùng. Khung tự động điền cung cấp cơ chế này ở dạng AutofillCallback.

Lớp (class) này cung cấp phương thức onAutofillEvent(View, int) mà ứng dụng sẽ gọi sau khi thay đổi trạng thái tự động điền được liên kết với một thành phần hiển thị. Ngoài ra còn có một phiên bản quá tải của phương thức này, bao gồm thông số childId mà ứng dụng của bạn có thể sử dụng với thành phần hiển thị ảo. Các trạng thái hiện có được định nghĩa là hằng số (constant) trong lệnh gọi lại.

Bạn có thể đăng ký một lệnh gọi lại bằng phương thức registerCallback() của lớp AutofillManager. Ví dụ về mã sau đây cho thấy cách khai báo một lệnh gọi lại cho các sự kiện tự động điền:

Kotlin

val afm = context.getSystemService(AutofillManager::class.java)

afm?.registerCallback(object : AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    override fun onAutofillEvent(view: View, event: Int) {
        super.onAutofillEvent(view, event)
        when (event) {
            EVENT_INPUT_HIDDEN -> {
                // The autofill affordance associated with the view was hidden.
            }
            EVENT_INPUT_SHOWN -> {
                // The autofill affordance associated with the view was shown.
            }
            EVENT_INPUT_UNAVAILABLE -> {
                // Autofill isn't available.
            }
        }

    }
})

Java

AutofillManager afm = getContext().getSystemService(AutofillManager.class);

afm.registerCallback(new AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    @Override
    public void onAutofillEvent(@NonNull View view, int event) {
        super.onAutofillEvent(view, event);
        switch (event) {
            case EVENT_INPUT_HIDDEN:
                // The autofill affordance associated with the view was hidden.
                break;
            case EVENT_INPUT_SHOWN:
                // The autofill affordance associated with the view was shown.
                break;
            case EVENT_INPUT_UNAVAILABLE:
                // Autofill isn't available.
                break;
        }
    }
});

Khi bạn cần loại bỏ lệnh gọi lại, hãy sử dụng phương thức unregisterCallback().

Tuỳ chỉnh tính năng tự động điền đối tượng có thể vẽ được đánh dấu

Khi một thành phần hiển thị có tính năng tự động điền, nền tảng này sẽ kết xuất một Drawable trên thành phần hiển thị đó để cho biết nội dung thành phần hiển thị đã được tự động điền. Theo mặc định, đối tượng có thể vẽ này là một hình chữ nhật đồng nhất có màu trong suốt và tối hơn một chút so với màu của giao diện dùng để vẽ nền. Bạn không cần thay đổi đối tượng có thể vẽ này, nhưng có thể tuỳ chỉnh bằng cách ghi đè mục android:autofilledHighlight của giao diện mà ứng dụng hoặc hoạt động sử dụng, như trình bày trong ví dụ sau:

res/values/styles.xml

<resources>
    <style name="MyAutofilledHighlight" parent="...">
        <item name="android:autofilledHighlight">@drawable/my_drawable</item>
    </style>
</resources>

res/drawable/my_drawable.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#4DFF0000" />
</shape>

AndroidManifest.xml

<application ...
    android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
    android:theme="@style/MyAutofilledHighlight">

Xác thực để tự động điền

Dịch vụ tự động điền có thể yêu cầu người dùng xác thực trước khi dịch vụ đó có thể hoàn tất các trường trong ứng dụng. Trong trường hợp này, hệ thống Android sẽ khởi động hoạt động xác thực của dịch vụ trong phạm vi ngăn xếp của hoạt động.

Bạn không cần phải cập nhật ứng dụng để hỗ trợ tính năng xác thực vì quá trình xác thực diễn ra trong dịch vụ. Tuy nhiên, bạn phải đảm bảo cấu trúc khung hiển thị của hoạt động được giữ nguyên khi hoạt động được bắt đầu lại (ví dụ: bằng cách tạo cấu trúc khung hiển thị trong onCreate(), không phải trong onStart() hoặc onResume()).

Bạn có thể xác minh cách hoạt động của ứng dụng khi một dịch vụ tự động điền yêu cầu xác thực bằng cách sử dụng HeuristicsService trên mẫu AutofillFramework và định cấu hình dịch vụ này để yêu cầu xác thực phản hồi điền. Bạn cũng có thể sử dụng mẫu BadViewStructureCreationSignInActivity để mô phỏng vấn đề này.

Chỉ định mã nhận dạng tự động điền cho thành phần hiển thị tuần hoàn

Các vùng chứa sử dụng lại khung hiển thị (chẳng hạn như lớp RecyclerView) rất hữu ích cho những ứng dụng cần cho thấy danh sách thành phần di chuyển dựa trên tập dữ liệu lớn. Khi vùng chứa di chuyển, hệ thống sử dụng lại các thành phần hiển thị trong bố cục, nhưng các thành phần hiển thị sau đó lại chứa nội dung mới. Nếu người dùng điền vào nội dung ban đầu của khung hiển thị, thì dịch vụ tự động điền sẽ giữ nguyên ý nghĩa logic của các khung hiển thị bằng cách sử dụng mã nhận dạng tự động điền. Sự cố sẽ xảy ra khi hệ thống sử dụng lại các khung hiển thị trong bố cục, các mã nhận dạng logic của khung hiển thị vẫn giữ nguyên, khiến dữ liệu người dùng tự động điền không chính xác được liên kết với một mã nhận dạng tự động điền.

Để giải quyết vấn đề này trên các thiết bị chạy Android 9 (API cấp 28) trở lên, bạn có thể quản lý rõ ràng mã tự động điền của các thành phần hiển thị mà RecyclerView sử dụng bằng những phương thức mới sau:

  • Phương thức getNextAutofillId() nhận một mã nhận dạng tự động điền mới dành riêng cho hoạt động.
  • Phương thức setAutofillId() đặt mã nhận dạng tự động điền logic duy nhất của thành phần hiển thị này trong hoạt động.

Giải quyết các vấn đề đã biết

Phần này trình bày giải pháp cho các vấn đề đã biết trong khung tự động điền.

Tính năng tự động điền khiến ứng dụng gặp sự cố trên Android 8.0, 8.1

Trên Android 8.0 (API cấp 26) và 8.1 (API cấp 27), tính năng tự động điền có thể khiến ứng dụng gặp sự cố trong một số trường hợp cụ thể. Để giải quyết các vấn đề tiềm ẩn, hãy gắn thẻ bất kỳ chế độ xem nào không được tự động điền bằng importantForAutofill=no. Bạn cũng có thể gắn thẻ toàn bộ hoạt động bằng importantForAutofill=noExcludeDescendants.

Không dùng hộp thoại đã đổi kích cho tính năng tự động điền

Trong Android 8.1 (API cấp 27) trở xuống, nếu một thành phần hiển thị trong hộp thoại (dialog) được đổi kích thước sau khi xuất hiện, thì thành phần hiển thị đó sẽ không được dùng để tự động điền. Các thành phần hiển thị như vậy không được đưa vào đối tượng AssistStructure mà hệ thống Android gửi đến dịch vụ tự động điền. Do đó, dịch vụ này không thể điền vào các thành phần hiển thị.

Để giải quyết vấn đề này, hãy thay thế thuộc tính token của các thông số cửa sổ hộp thoại bằng thuộc tính token của hoạt động tạo hộp thoại. Sau khi bạn xác thực để đảm bảo rằng tính năng tự động điền đã bật, hãy lưu các tham số cửa sổ trong phương thức onWindowAttributesChanged() của lớp kế thừa từ Dialog. Sau đó, hãy thay thế thuộc tính token của các tham số đã lưu bằng thuộc tính token của hoạt động mẹ trong phương thức onAttachedToWindow().

Đoạn mã sau đây cho thấy một lớp (class) triển khai giải pháp:

Kotlin

class MyDialog(context: Context) : Dialog(context) {

    // Used to store the dialog window parameters.
    private var token: IBinder? = null

    private val isDialogResizedWorkaroundRequired: Boolean
        get() {
            if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
                return false
            }
            val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                context.getSystemService(AutofillManager::class.java)
            } else {
                null
            }
            return autofillManager?.isEnabled ?: false
        }

    override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) {
        if (params.token == null && token != null) {
            params.token = token
        }

        super.onWindowAttributesChanged(params)
    }

    override fun onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired) {
            token = ownerActivity!!.window.attributes.token
        }

        super.onAttachedToWindow()
    }

}

Java

public class MyDialog extends Dialog {

    public MyDialog(Context context) {
        super(context);
    }

    // Used to store the dialog window parameters.
    private IBinder token;

    @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        if (params.token == null && token != null) {
            params.token = token;
        }

        super.onWindowAttributesChanged(params);
    }

    @Override
    public void onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired()) {
            token = getOwnerActivity().getWindow().getAttributes().token;
        }

        super.onAttachedToWindow();
    }

    private boolean isDialogResizedWorkaroundRequired() {
        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O
                || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
            return false;
        }
        AutofillManager autofillManager =
                null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            autofillManager = getContext().getSystemService(AutofillManager.class);
        }
        return autofillManager != null && autofillManager.isEnabled();
    }

}

Để tránh các hoạt động không cần thiết, đoạn mã sau đây cho biết cách kiểm tra xem tính năng tự động điền có được hỗ trợ trong thiết bị và cho người dùng hiện tại hay không, cũng như có bắt buộc phải thực hiện giải pháp này hay không:

Kotlin

// AutofillExtensions.kt

fun Context.isDialogResizedWorkaroundRequired(): Boolean {
    // After the issue is resolved on Android, you should check if the
    // workaround is still required for the current device.
    return isAutofillAvailable()
}

fun Context.isAutofillAvailable(): Boolean {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        // The autofill framework is only available on Android 8.0
        // or higher.
        return false
    }

    val afm = getSystemService(AutofillManager::class.java)
    // Return true if autofill is supported by the device and enabled
    // for the current user.
    return afm != null && afm.isEnabled
}

Java

public class AutofillHelper {

    public static boolean isDialogResizedWorkaroundRequired(Context context) {
        // After the issue is resolved on Android, you should check if the
        // workaround is still required for the current device.
        return isAutofillAvailable(context);
    }

    public static boolean isAutofillAvailable(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // The autofill framework is only available on Android 8.0
            // or higher.
            return false;
        }

        AutofillManager afm = context.getSystemService(AutofillManager.class);
        // Return true if autofill is supported by the device and enabled
        // for the current user.
        return afm != null && afm.isEnabled();
    }
}

Kiểm thử tính năng tự động điền trong ứng dụng

Hầu hết ứng dụng đều dùng được dịch vụ tự động điền mà không có thay đổi gì. Tuy nhiên, bạn có thể tối ưu hoá ứng dụng để đảm bảo ứng dụng hoạt động hiệu quả nhất có thể khi dùng dịch vụ tự động điền. Sau khi tối ưu hoá ứng dụng, bạn nên kiểm tra ứng dụng để đảm bảo ứng dụng hoạt động như dự kiến khi dùng dịch vụ tự động điền.

Bạn nên sử dụng trình mô phỏng hoặc thiết bị thực tế chạy Android 8.0 (API cấp 26) trở lên để kiểm thử ứng dụng. Để biết thêm thông tin về cách tạo trình mô phỏng, hãy xem nội dung Tạo và quản lý thiết bị ảo.

Cài đặt dịch vụ tự động điền

Trước khi có thể kiểm thử tính năng tự động điền, ứng dụng cần cài đặt một ứng dụng khác cung cấp dịch vụ tự động điền. Bạn có thể dùng ứng dụng của bên thứ ba cho mục đích này, nhưng việc sử dụng dịch vụ tự động điền mẫu sẽ dễ dàng hơn vì không cần đăng ký dịch vụ bên thứ ba nào.

Bạn có thể sử dụng mẫu khung tự động điền Java | Kotlin của Android để kiểm thử ứng dụng với các dịch vụ tự động điền. Ứng dụng mẫu cung cấp một dịch vụ tự động điền và các lớp ứng dụng Activity mà bạn có thể sử dụng để kiểm thử quy trình làm việc trước khi dùng trong ứng dụng. Trang này đề cập đến ứng dụng mẫu android-AutofillFramework.

Sau khi cài đặt ứng dụng, bạn nên bật dịch vụ tự động điền trong phần cài đặt hệ thống. Bạn có thể bật dịch vụ này bằng cách chuyển đến phần Settings (Cài đặt) > System (Hệ thống) > Languages & input (Ngôn ngữ và nhập liệu) > Advanced (Nâng cao) > Input assistance (Hỗ trợ nhập liệu) > Autofill service (Dịch vụ tự động điền).

Phân tích yêu cầu về dữ liệu

Để kiểm thử ứng dụng bằng dịch vụ tự động điền, dịch vụ này cần có dữ liệu để có thể điền vào ứng dụng. Dịch vụ này cũng cần nắm được loại dữ liệu dự kiến trong các khung hiển thị của ứng dụng. Ví dụ: nếu ứng dụng có khung hiển thị cần điền tên người dùng, thì dịch vụ này phải có tập dữ liệu chứa tên người dùng và một số cơ chế để biết rằng khung hiển thị cần đến dữ liệu như vậy.

Bạn nên cho dịch vụ biết loại dữ liệu dự kiến trong các khung hiển thị bằng cách đặt thuộc tính android:autofillHints. Một số dịch vụ sử dụng các phương pháp phỏng đoán tinh vi để xác định loại dữ liệu, nhưng một số dịch vụ khác (chẳng hạn như ứng dụng mẫu này) dựa vào nhà phát triển để cung cấp thông tin này. Ứng dụng của bạn dùng dịch vụ tự động điền hiệu quả hơn nếu bạn đặt giá trị cho thuộc tính android:autofillHints trong các khung hiển thị có liên quan đến tính năng tự động điền.

Chạy kiểm thử

Sau khi phân tích các yêu cầu về dữ liệu, bạn có thể chạy kiểm thử, bao gồm cả hoạt động lưu dữ liệu kiểm thử trong dịch vụ tự động điền và kích hoạt tính năng tự động điền trong ứng dụng.

Lưu dữ liệu trong dịch vụ

Các bước sau đây cho biết cách lưu dữ liệu trong dịch vụ tự động điền hiện đang hoạt động:

  1. Mở ứng dụng chứa thành phần hiển thị cần đến loại dữ liệu bạn muốn sử dụng trong quá trình kiểm thử. Ứng dụng mẫu android-AutofillFramework cung cấp giao diện người dùng với các thành phần hiển thị cần đến một số loại dữ liệu, chẳng hạn như số thẻ tín dụng và tên người dùng.
  2. Nhấn vào thành phần hiển thị lưu giữ loại dữ liệu bạn cần.
  3. Nhập giá trị vào thành phần hiển thị.
  4. Nhấn vào nút xác nhận, chẳng hạn như Sign in (Đăng nhập) hoặc Submit (Gửi).

    Thường thì bạn phải gửi biểu mẫu trước khi dịch vụ tìm cách lưu dữ liệu này.

  5. Hệ thống sẽ cho thấy hộp thoại yêu cầu bạn cho phép lưu dữ liệu. Hộp thoại đó cho biết tên của dịch vụ hiện đang hoạt động.

    Hãy xác minh rằng đây là dịch vụ bạn muốn sử dụng trong quá trình kiểm thử rồi nhấn vào Save (Lưu).

Nếu Android không cho thấy hộp thoại cấp quyền hoặc nếu dịch vụ đó không phải là dịch vụ bạn muốn sử dụng trong quá trình kiểm thử, hãy kiểm tra trong phần cài đặt hệ thống để đảm bảo dịch vụ đó đang hoạt động.

Kích hoạt tính năng tự động điền trong ứng dụng

Các bước sau đây cho biết cách kích hoạt tính năng tự động điền trong ứng dụng:

  1. Mở ứng dụng rồi chuyển đến hoạt động có thành phần hiển thị mà bạn muốn kiểm thử.
  2. Nhấn vào thành phần hiển thị cần được điền vào.
  3. Hệ thống sẽ cho thấy giao diện người dùng tự động điền, trong đó chứa các tập dữ liệu có thể điền vào thành phần hiển thị, như trong Hình 1.
  4. Nhấn vào tập dữ liệu chứa dữ liệu mà bạn muốn sử dụng. Thành phần hiển thị sẽ cho thấy dữ liệu đã lưu trữ trước đó trong dịch vụ.
Giao diện người dùng tự động điền cho thấy
Hình 1. Giao diện người dùng tự động điền cho thấy các tập dữ liệu hiện có.

Nếu Android không cho thấy giao diện người dùng tự động điền, thì bạn có thể thử các phương án khắc phục sự cố sau:

  • Hãy kiểm tra các khung hiển thị trong ứng dụng để chắc chắn về việc sử dụng đúng giá trị trong thuộc tính android:autofillHints. Để biết danh sách giá trị có thể xuất hiện cho thuộc tính này, hãy xem các hằng số có tiền tố AUTOFILL_HINT trong lớp View.
  • Kiểm tra để đảm bảo thuộc tính android:importantForAutofill được thiết lập thành một giá trị không phải là no trên khung hiển thị sẽ được điền vào, hoặc được thiết lập thành một giá trị không phải là noExcludeDescendants trên khung hiển thị đó hoặc trên một trong số khung hiển thị mẹ tương ứng.