Mengoptimalkan aplikasi Anda untuk isi otomatis

Aplikasi yang menggunakan tampilan standar berfungsi dengan Framework IsiOtomatis tanpa memerlukan konfigurasi khusus. Anda juga dapat mengoptimalkan cara kerja aplikasi dengan framework.

Menyiapkan lingkungan isi otomatis

Bagian ini menjelaskan cara menyiapkan fungsi isi otomatis dasar untuk aplikasi Anda.

Mengonfigurasi layanan isi otomatis

Layanan isi otomatis harus dikonfigurasi di perangkat agar aplikasi Anda dapat menggunakan framework isi otomatis. Meskipun sebagian besar ponsel dan tablet yang menjalankan Android 8.0 (level API 26) dan versi lebih baru sudah dilengkapi dengan layanan isi otomatis, sebaiknya gunakan layanan pengujian saat menguji aplikasi, seperti layanan isi otomatis dalam contoh framework isi otomatis Android. Saat menggunakan emulator, setel layanan isi otomatis secara eksplisit, karena emulator mungkin tidak disertakan dengan layanan default.

Setelah menginstal layanan isi otomatis pengujian dari aplikasi contoh, aktifkan layanan isi otomatis dengan membuka Settings > System > Languages & input > Advanced > Input assistance > Autofill service.

Untuk mengetahui informasi selengkapnya tentang cara mengonfigurasi emulator untuk menguji isi otomatis, lihat Menguji aplikasi dengan isi otomatis.

Memberikan petunjuk untuk isi otomatis

Layanan isi otomatis menentukan jenis setiap tampilan menggunakan heuristik. Namun, jika aplikasi Anda bergantung pada heuristik tersebut, perilaku isi otomatis mungkin akan berubah secara tidak terduga saat Anda mengupdate aplikasi. Untuk memastikan layanan isi otomatis mengidentifikasi faktor bentuk aplikasi Anda dengan benar, berikan petunjuk isi otomatis.

Anda dapat menetapkan petunjuk isi otomatis menggunakan atribut android:autofillHints. Contoh berikut menetapkan petunjuk "password" pada EditText:

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

Anda juga dapat menyetel petunjuk secara terprogram menggunakan metode setAutofillHints() , seperti yang ditunjukkan pada contoh berikut:

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

Menyertakan konstanta petunjuk yang telah ditentukan sebelumnya

Framework isi otomatis tidak memvalidasi petunjuk, tetapi diteruskan tanpa perubahan atau validasi ke layanan isi otomatis. Meskipun Anda dapat menggunakan nilai apa pun, class View dan AndroidX HintConstants berisi daftar konstanta petunjuk yang didukung secara resmi.

Dengan menggunakan kombinasi konstanta ini, Anda dapat membuat tata letak untuk skenario isi otomatis yang umum:

Kredensial akun

Pada formulir login, Anda dapat menyertakan petunjuk kredensial akun seperti AUTOFILL_HINT_USERNAME dan AUTOFILL_HINT_PASSWORD.

Untuk membuat akun baru, atau saat pengguna mengubah nama pengguna dan sandi mereka, Anda dapat menggunakan AUTOFILL_HINT_NEW_USERNAME dan AUTOFILL_HINT_NEW_PASSWORD.

Info kartu kredit

Saat meminta info kartu kredit, Anda dapat menggunakan petunjuk seperti AUTOFILL_HINT_CREDIT_CARD_NUMBER dan AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE.

Untuk tanggal habis masa berlaku kartu kredit, lakukan salah satu opsi berikut:

Alamat fisik

Untuk kolom formulir alamat fisik, Anda dapat menggunakan petunjuk seperti berikut:

Nama orang

Saat meminta nama orang, Anda dapat menggunakan petunjuk seperti berikut:

.

Nomor telepon

Untuk nomor telepon, Anda dapat menggunakan kode berikut:

Sandi sekali pakai (OTP)

Untuk sandi sekali pakai dalam satu tampilan, Anda dapat menggunakan AUTOFILL_HINT_SMS_OTP.

Untuk beberapa tampilan dengan setiap tampilan dipetakan menjadi satu digit OTP, Anda dapat menggunakan metode generateSmsOtpHintForCharacterPosition() untuk menghasilkan petunjuk per karakter.

Menandai kolom sebagai penting untuk isi otomatis

Anda dapat menyertakan masing-masing kolom di aplikasi dalam struktur tampilan untuk tujuan isi otomatis. Secara default, tampilan menggunakan mode IMPORTANT_FOR_AUTOFILL_AUTO yang memungkinkan Android menggunakan heuristiknya untuk menentukan apakah tampilan penting untuk isi otomatis.

Namun, ada kasus saat tampilan, struktur tampilan, atau seluruh aktivitas tidak penting untuk isi otomatis:

  • Kolom CAPTCHA dalam aktivitas login
  • Tampilan tempat pengguna membuat konten, seperti teks atau editor spreadsheet
  • Tampilan dalam beberapa aktivitas dalam game, seperti yang menampilkan gameplay

Anda dapat menyetel nilai penting tampilan untuk isi otomatis menggunakan atribut android:importantForAutofill:

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

Nilai importantForAutofill dapat berupa salah satu dari nilai berikut:

auto
Mengizinkan Sistem Android menggunakan heuristiknya untuk menentukan apakah tampilan penting untuk isi otomatis atau tidak.
no
Tampilan ini tidak penting untuk isi otomatis.
noExcludeDescendants
Tampilan ini dan turunannya tidak penting untuk isi otomatis.
yes
Tampilan ini penting untuk isi otomatis.
yesExcludeDescendants
Tampilan ini penting, tetapi turunannya tidak penting untuk isi otomatis.

Anda juga dapat menggunakan metode 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);

Anda dapat mendeklarasikan contoh kasus penggunaan sebelumnya yang tidak penting untuk isi otomatis sebagai berikut:

  • Kolom CAPTCHA dalam aktivitas login: gunakan android:importantForAutofill="no" atau IMPORTANT_FOR_AUTOFILL_NO untuk menandai tampilan ini sebagai tidak penting.
  • Tampilan tempat pengguna membuat konten: gunakan android:importantForAutofill="noExcludeDescendants" atau IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS untuk menandai seluruh struktur tampilan sebagai tidak penting.
  • Tampilan di beberapa aktivitas dalam game: gunakan android:importantForAutofill="noExcludeDescendants" atau IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS untuk menandai seluruh struktur tampilan sebagai tidak penting.

Mengaitkan situs dan data aplikasi seluler

Layanan isi otomatis seperti Isi Otomatis dengan Google dapat membagikan data login pengguna di antara beberapa browser dan perangkat Android setelah aplikasi dan situs dikaitkan. Saat pengguna memilih layanan isi otomatis yang sama di kedua platform, login ke aplikasi web akan membuat kredensial login tersedia untuk isi otomatis saat mereka login ke aplikasi Android yang sesuai.

Untuk mengaitkan aplikasi Android dengan situs, lakukan host Digital Asset Links dengan hubungan delegate_permission/common.get_login_creds di situs Anda. Selanjutnya, deklarasikan pengaitan di file AndroidManifest.xml aplikasi Anda. Untuk petunjuk detail tentang cara mengaitkan situs dengan aplikasi Android, baca Mengaktifkan login otomatis di seluruh aplikasi dan situs.

Menyelesaikan alur kerja isi otomatis

Bagian ini menjelaskan skenario tertentu yang dapat Anda gunakan untuk meningkatkan fungsi isi otomatis bagi pengguna aplikasi Anda.

Menentukan apakah isi otomatis diaktifkan atau tidak

Pengguna dapat mengaktifkan atau menonaktifkan isi otomatis serta mengubah layanan isi otomatis dengan membuka Settings > System > Languages & input > Advanced > Input assistance > Autofill service. Aplikasi Anda tidak dapat mengganti setelan isi otomatis pengguna, tetapi Anda dapat menerapkan fungsi isi otomatis tambahan di aplikasi, atau dalam tampilan tertentu aplikasi, jika isi otomatis tersedia bagi pengguna.

Misalnya, TextView menampilkan entri isi otomatis di menu tambahan jika isi otomatis diaktifkan bagi pengguna. Untuk memeriksa apakah isi otomatis diaktifkan bagi pengguna, panggil metode isEnabled() objek AutofillManager.

Untuk memastikan pengalaman pendaftaran dan login Anda dioptimalkan bagi pengguna tanpa isi otomatis, terapkan login Sekali Ketuk.

Memaksa permintaan isi otomatis

Terkadang, Anda mungkin perlu memaksa permintaan isi otomatis agar terjadi sebagai respons atas tindakan pengguna. Misalnya, TextView menawarkan item menu isi otomatis saat pengguna menyentuh lama tampilan. Contoh kode berikut menunjukkan cara memaksa permintaan isi otomatis:

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

Anda juga dapat menggunakan metode cancel() untuk membatalkan konteks isi otomatis saat ini. Fungsi ini dapat berguna jika Anda memiliki tombol yang menghapus kolom pada halaman login.

Menggunakan jenis isi otomatis yang benar untuk data di kontrol alat pilih

Alat pilih dapat berguna untuk isi otomatis dengan menyediakan UI yang memungkinkan pengguna mengubah nilai kolom yang menyimpan data tanggal atau waktu. Misalnya, dalam formulir kartu kredit, pemilih tanggal memungkinkan pengguna memasukkan atau mengubah tanggal habis masa berlaku kartu kredit. Namun, Anda harus menggunakan tampilan lain, seperti EditText, untuk menampilkan data saat alat pilih tidak terlihat.

Objek EditText secara native menginginkan data isi otomatis jenis AUTOFILL_TYPE_TEXT. Jika menggunakan jenis data yang berbeda, Anda harus membuat tampilan kustom yang diturunkan dari EditText dan mengimplementasikan metode yang diperlukan untuk menangani jenis data yang sesuai. Misalnya, jika Anda memiliki kolom tanggal, terapkan metode dengan logika yang menangani nilai jenis AUTOFILL_TYPE_DATE secara benar.

Saat Anda menentukan jenis data isi otomatis, layanan isi otomatis dapat membuat representasi yang sesuai dari data yang ditampilkan dalam tampilan. Untuk mengetahui informasi selengkapnya, lihat Menggunakan alat pilih dengan isi otomatis.

Menyelesaikan konteks isi otomatis

Framework isi otomatis akan menyimpan input pengguna untuk penggunaan mendatang dengan menampilkan dialog "Simpan untuk isi otomatis?" setelah konteks isi otomatis selesai. Biasanya, konteks isi otomatis selesai saat aktivitas selesai. Namun, ada beberapa situasi saat Anda harus memberitahukan framework secara eksplisit; misalnya, jika menggunakan aktivitas yang sama tetapi berbeda fragmen untuk layar login dan konten. Pada situasi khusus ini, Anda dapat menyelesaikan konteks secara eksplisit dengan memanggil AutofillManager.commit().

Dukungan untuk tampilan kustom

Tampilan kustom dapat menentukan metadata yang diekspos ke framework isi otomatis menggunakan API isi otomatis. Beberapa tampilan berfungsi sebagai penampung turunan virtual, seperti tampilan yang berisi UI yang dirender OpenGL. Tampilan ini harus menggunakan API untuk menentukan struktur informasi yang digunakan dalam aplikasi sebelum dapat berfungsi dengan framework isi otomatis.

Jika aplikasi Anda menggunakan tampilan kustom, pertimbangkan skenario berikut:

  • Tampilan kustom menyediakan struktur tampilan standar, atau struktur tampilan default.
  • Tampilan kustom memiliki struktur virtual, atau struktur tampilan yang tidak tersedia untuk framework isi otomatis.

Tampilan kustom dengan struktur tampilan standar

Tampilan kustom dapat menentukan metadata yang diperlukan isi otomatis agar berfungsi. Pastikan tampilan kustom Anda mengelola metadata dengan tepat agar dapat berfungsi dengan framework isi otomatis. Tampilan kustom harus melakukan tindakan berikut:

  • Tangani nilai isi otomatis yang dikirim framework ke aplikasi Anda.
  • Berikan jenis dan nilai isi otomatis ke framework.

Saat isi otomatis dipicu, framework isi otomatis akan memanggil autofill() pada tampilan dan mengirimkan nilai yang akan digunakan tampilan Anda. Terapkan autofill() untuk menentukan cara tampilan kustom Anda menangani nilai isi otomatis.

Tampilan Anda harus menentukan jenis dan nilai isi otomatis dengan mengganti masing-masing metode getAutofillType() dan getAutofillValue() .

Terakhir, isi otomatis tidak boleh mengisi tampilan jika pengguna tidak dapat memberikan nilai untuk tampilan dalam status saat ini—misalnya, jika tampilan dinonaktifkan. Dalam hal ini, getAutofillType() harus menampilkan AUTOFILL_TYPE_NONE, getAutofillValue() harus menampilkan null, dan autofill() tidak boleh melakukan apa pun.

Kasus berikut memerlukan langkah tambahan agar dapat berfungsi dengan benar dalam framework:

  • Tampilan kustom dapat diedit.
  • Tampilan kustom berisi data sensitif.

Tampilan kustom dapat diedit

Jika tampilan dapat diedit, beri tahu framework isi otomatis tentang perubahan dengan memanggil notifyValueChanged() pada objek AutofillManager.

Tampilan kustom berisi data sensitif

Jika tampilan berisi informasi identitas pribadi (PII) seperti alamat email, nomor kartu kredit, dan sandi, tampilan tersebut harus ditandai sebagai sensitif.

Secara umum, tampilan yang kontennya berasal dari resource statis tidak berisi data sensitif, sedangkan tampilan yang kontennya disetel secara dinamis mungkin berisi data sensitif. Misalnya, label yang berisi masukkan nama pengguna tidak berisi data sensitif, sedangkan label yang berisi Halo, John berisi data sensitif.

Framework isi otomatis mengasumsikan bahwa semua data bersifat sensitif secara default. Anda dapat menandai data yang tidak sensitif.

Untuk menandai apakah tampilan berisi data sensitif, implementasikan onProvideAutofillStructure() dan panggil setDataIsSensitive() pada ViewStructure.

Contoh kode berikut menunjukkan cara menandai data dalam struktur tampilan sebagai tidak sensitif:

Kotlin

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

    structure.setDataIsSensitive(false)
}

Java

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

    structure.setDataIsSensitive(false);
}

Jika tampilan hanya menerima nilai yang ditetapkan sebelumnya, Anda dapat menggunakan metode setAutofillOptions() untuk menyetel opsi yang dapat digunakan untuk isi otomatis tampilan ini. Secara khusus, tampilan dengan jenis isi otomatis AUTOFILL_TYPE_LIST harus menggunakan metode ini karena layanan isi otomatis dapat melakukan fungsinya secara lebih baik jika mengetahui opsi yang tersedia untuk mengisi tampilan.

Tampilan yang menggunakan adaptor, seperti Spinner, adalah kasus yang serupa. Misalnya, indikator lingkaran berputar yang menyediakan tahun yang dibuat secara dinamis berdasarkan tahun berjalan untuk digunakan dalam kolom habis masa berlaku kartu kredit dapat menerapkan metode getAutofillOptions() antarmuka Adapter untuk menyediakan daftar tahun.

Tampilan yang menggunakan ArrayAdapter juga dapat menyediakan daftar nilai. ArrayAdapter otomatis menetapkan opsi isi otomatis untuk resource statis. Jika Anda memberikan nilai secara dinamis, ganti getAutofillOptions().

Tampilan kustom dengan struktur virtual

Framework isi otomatis memerlukan struktur tampilan agar dapat mengedit dan menyimpan informasi di UI aplikasi. Struktur tampilan tidak tersedia untuk framework dalam situasi berikut:

  • Aplikasi menggunakan mesin rendering level rendah, seperti OpenGL, untuk me-render UI.
  • Aplikasi menggunakan instance Canvas untuk menggambar UI.

Pada kasus ini, Anda dapat menentukan struktur tampilan dengan menerapkan onProvideAutofillVirtualStructure() dan mengikuti langkah-langkah berikut:

  1. Tingkatkan jumlah turunan struktur tampilan dengan memanggil addChildCount().
  2. Tambahkan turunan dengan memanggil newChild().
  3. Setel ID isi otomatis untuk turunan dengan memanggil setAutofillId().
  4. Setel properti yang relevan, seperti nilai dan jenis isi otomatis.
  5. Jika data pada turunan virtual sensitif, teruskan true ke setDataIsSensitive(); jika tidak, teruskan false.

Cuplikan kode berikut menunjukkan cara membuat turunan baru dalam struktur virtual:

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, such as when 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 when
    // 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, such as when the child is
    // a spinner.
    CharSequence childAutofillOptions[] = { "option1", "option2" };
    child.setAutofillOptions(childAutofillOptions);

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

Saat elemen dalam struktur virtual berubah, beri tahu framework dengan menjalankan tugas berikut:

  • Jika fokus di dalam turunan berubah, panggil notifyViewEntered() dan notifyViewExited() pada objek AutofillManager.
  • Jika nilai turunan berubah, panggil notifyValueChanged() pada objek AutofillManager.
  • Jika hierarki tampilan tidak lagi tersedia karena pengguna menyelesaikan langkah dalam alur kerja, seperti saat login menggunakan formulir login, panggil commit() pada objek AutofillManager.
  • Jika hierarki tampilan tidak valid karena pengguna membatalkan langkah dalam alur kerja, seperti saat pengguna mengetuk tombol yang menghapus formulir login, panggil cancel() pada objek AutofillManager.

Menggunakan callback pada peristiwa isi otomatis

Jika aplikasi Anda menyediakan tampilan pelengkapan otomatisnya sendiri, Anda memerlukan mekanisme yang memberi tahu aplikasi untuk mengaktifkan atau menonaktifkan tampilan sebagai respons terhadap perubahan dalam kemampuan UI isi otomatis. Framework isi otomatis menyediakan mekanisme ini dalam bentuk AutofillCallback.

Class ini menyediakan metode onAutofillEvent(View, int) yang dipanggil aplikasi setelah perubahan dalam status isi otomatis terkait tampilan. Metode ini juga memiliki versi overload yang mencakup parameter childId yang dapat digunakan aplikasi Anda dengan tampilan virtual. Status yang tersedia didefinisikan sebagai konstanta pada callback.

Anda dapat mendaftarkan callback menggunakan metode registerCallback() dari class AutofillManager. Contoh kode berikut menunjukkan cara mendeklarasikan callback untuk peristiwa isi otomatis:

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

Pada waktu menghapus callback, gunakan metode unregisterCallback() .

Menyesuaikan drawable yang disorot isi otomatis

Saat tampilan diisi otomatis, platform akan merender Drawable di atas tampilan untuk menunjukkan bahwa konten tampilan diisi otomatis. Secara default, drawable ini adalah persegi panjang solid dengan warna transparan yang sedikit lebih gelap daripada warna tema yang digunakan untuk menggambar latar belakang. Drawable tidak perlu diubah, tetapi dapat disesuaikan dengan mengganti item android:autofilledHighlight dari tema yang digunakan oleh aplikasi atau aktivitas, seperti yang ditunjukkan dalam contoh berikut:

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

Autentikasi untuk isi otomatis

Layanan isi otomatis dapat mengharuskan pengguna untuk melakukan autentikasi sebelum layanan dapat menyelesaikan kolom di aplikasi, sehingga sistem Android akan meluncurkan aktivitas autentikasi layanan sebagai bagian dari stack aktivitas Anda.

Anda tidak perlu mengupdate aplikasi untuk mendukung autentikasi karena autentikasi terjadi dalam layanan. Namun, Anda harus memastikan agar struktur tampilan aktivitas dipertahankan saat aktivitas dimulai ulang (misalnya, dengan membuat struktur tampilan di onCreate(), bukan di onStart() atau onResume().

Anda dapat memverifikasi perilaku aplikasi jika layanan isi otomatis memerlukan autentikasi dengan menggunakan HeuristicsService dari contoh AutofillFramework dan mengonfigurasinya agar memerlukan autentikasi respons pengisian. Anda juga dapat menggunakan contoh BadViewStructureCreationSignInActivity untuk mengemulasi masalah ini.

Menetapkan ID isi otomatis untuk tampilan yang didaur ulang

Penampung yang mendaur ulang tampilan, seperti class RecyclerView, berguna untuk aplikasi yang perlu menampilkan daftar scroll elemen berdasarkan set data besar. Saat penampung di-scroll, sistem akan menggunakan kembali tampilan dalam tata letak, tetapi tampilan akan berisi konten baru.

Jika konten awal tampilan daur ulang diisi, layanan isi otomatis akan mempertahankan makna logis tampilan menggunakan ID isi otomatisnya. Karena sistem menggunakan kembali tampilan dalam tata letak, masalah akan terjadi jika ID logis tampilan tetap sama, yang menyebabkan isi otomatis data pengguna yang salah dikaitkan dengan ID isi otomatis.

Untuk mengatasi masalah ini di perangkat yang menjalankan Android 9 (level API 28) dan versi lebih baru, secara eksplisit kelola tampilan ID isi otomatis yang digunakan oleh RecyclerView menggunakan metode berikut:

  • Metode getNextAutofillId() mendapatkan ID isi otomatis baru yang unik untuk aktivitas tersebut.
  • Metode setAutofillId() menyetel ID isi otomatis yang unik dan logis dari tampilan ini dalam aktivitas tersebut.

Mengatasi masalah umum

Bagian ini memberikan penyelesaian masalah umum dalam framework isi otomatis.

Isi otomatis menyebabkan aplikasi error pada Android 8.0, 8.1

Di Android 8.0 (level API 26) dan 8.1 (level API 27), fitur isi otomatis dapat menyebabkan aplikasi Anda error pada skenario tertentu. Untuk mengatasi kemungkinan masalah, beri tag setiap tampilan yang tidak diisi otomatis dengan importantForAutofill=no. Anda juga dapat memberi tag seluruh aktivitas dengan importantForAutofill=noExcludeDescendants.

Dialog yang diubah ukurannya tidak dipertimbangkan untuk isi otomatis

Di Android 8.1 (level API 27) dan yang lebih rendah, jika tampilan dalam dialog diubah ukurannya setelah ditampilkan, tampilan tidak dipertimbangkan untuk isi otomatis. Tampilan tersebut tidak disertakan dalam objek AssistStructure yang dikirimkan sistem Android ke layanan isi otomatis. Hasilnya, layanan tidak dapat mengisi tampilan.

Untuk mengatasi masalah ini, ganti properti token dalam parameter jendela dialog dengan properti token aktivitas yang membuat dialog. Setelah memvalidasi bahwa isi otomatis telah diaktifkan, simpan parameter jendela di metode onWindowAttributesChanged() class yang mewarisi dari Dialog. Selanjutnya, ganti properti token dalam parameter yang disimpan dengan properti token dalam aktivitas induk pada metode onAttachedToWindow().

Cuplikan kode berikut menunjukkan class yang menerapkan solusi tersebut:

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

}

Untuk menghindari operasi yang tidak perlu, cuplikan kode berikut menunjukkan cara memeriksa apakah isi otomatis didukung di perangkat dan diaktifkan untuk pengguna saat ini, serta apakah solusi ini diwajibkan:

Kotlin

// AutofillExtensions.kt

fun Context.isDialogResizedWorkaroundRequired(): Boolean {
    // After the issue is resolved on Android, check whether 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 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, check whether 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 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();
    }
}

Menguji aplikasi Anda dengan isi otomatis

Setelah Anda mengoptimalkan aplikasi agar berfungsi dengan layanan isi otomatis, uji apakah aplikasi berfungsi sebagaimana mestinya dengan layanan isi otomatis.

Gunakan emulator atau perangkat fisik yang menjalankan Android 8.0 (level API 26) atau versi lebih baru untuk menguji aplikasi. Untuk mengetahui informasi selengkapnya tentang cara membuat emulator, baca Membuat dan mengelola perangkat virtual.

Menginstal layanan isi otomatis

Sebelum dapat menguji aplikasi dengan fitur isi otomatis, Anda perlu menginstal aplikasi lain yang menyediakan layanan isi otomatis. Anda dapat menggunakan aplikasi pihak ketiga untuk tujuan ini, tetapi akan lebih mudah jika menggunakan layanan isi otomatis contoh sehingga tidak perlu mendaftar ke layanan pihak ketiga.

Anda dapat menggunakan contoh framework isi otomatis Android di Java untuk menguji aplikasi dengan layanan isi otomatis. Aplikasi contoh menyediakan layanan isi otomatis dan class Activity klien yang dapat digunakan untuk menguji alur kerja sebelum menggunakannya dengan aplikasi Anda. Halaman ini merujuk pada aplikasi contoh android-AutofillFramework.

Setelah Anda menginstal aplikasi, aktifkan layanan isi otomatis di setelan sistem emulator dengan membuka Settings > System > Languages & input > Advanced > Input assistance > Autofill service.

Menganalisis persyaratan data

Untuk menguji aplikasi Anda dengan layanan isi otomatis, layanan harus memiliki data yang dapat digunakan untuk mengisi aplikasi. Layanan ini juga harus memahami jenis data yang diharapkan dalam tampilan aplikasi. Misalnya, jika aplikasi memiliki tampilan yang meminta nama pengguna, layanan harus memiliki set data yang berisi nama pengguna dan mekanisme tertentu untuk mengetahui bahwa tampilan ini meminta data tersebut.

Beri tahu layanan jenis data yang diharapkan dalam tampilan dengan menyetel atribut android:autofillHints. Beberapa layanan menggunakan heuristik canggih untuk menentukan jenis data, tetapi yang lain, seperti aplikasi contoh, bergantung pada developer untuk menyediakan informasi ini. Aplikasi Anda akan berfungsi lebih baik dengan layanan isi otomatis jika Anda menyetel atribut android:autofillHints pada tampilan yang relevan untuk isi otomatis.

Menjalankan pengujian

Setelah menganalisis persyaratan data, Anda dapat menjalankan pengujian, yang mencakup menyimpan data pengujian di layanan isi otomatis dan memicu isi otomatis di aplikasi Anda.

Menyimpan data di layanan

Untuk menyimpan data di layanan isi otomatis yang saat ini aktif, lakukan hal berikut:

  1. Buka aplikasi yang berisi tampilan yang meminta jenis data yang ingin digunakan selama pengujian. Aplikasi contoh android-AutofillFramework menyediakan UI dengan tampilan yang meminta beberapa jenis data, seperti nomor kartu kredit dan nama pengguna.
  2. Ketuk tampilan yang menyimpan jenis data yang diperlukan.
  3. Masukkan nilai ke dalam tampilan.
  4. Ketuk tombol konfirmasi, seperti Sign in atau Submit. Anda biasanya harus mengirimkan formulir sebelum layanan menyimpan data.
  5. Verifikasi permintaan izin dari dialog sistem. Dialog sistem akan menampilkan nama layanan yang sedang aktif dan menanyakan apakah ini adalah layanan yang ingin Anda gunakan dalam pengujian. Jika Anda ingin menggunakan layanan, ketuk Save.

Jika Android tidak menampilkan dialog izin, atau layanan bukan yang ingin Anda gunakan dalam pengujian, periksa apakah layanan tersebut sedang aktif di setelan sistem.

Memicu isi otomatis di aplikasi

Untuk memicu isi otomatis di aplikasi, lakukan hal berikut:

  1. Buka aplikasi, lalu buka aktivitas yang memiliki tampilan yang ingin diuji.
  2. Ketuk tampilan yang perlu diisi.
  3. Sistem akan menampilkan UI isi otomatis, yang berisi set data yang dapat mengisi tampilan, seperti ditunjukkan pada Gambar 1.
  4. Ketuk set data berisi data yang ingin Anda gunakan. Tampilan ini menampilkan data yang sebelumnya disimpan di layanan.
UI isi otomatis menampilkan “dataset-2” sebagai set data yang tersedia
Gambar 1. UI isi otomatis menampilkan set data yang tersedia.

Jika Android tidak menampilkan UI isi otomatis, Anda dapat mencoba opsi pemecahan masalah berikut:

  • Pastikan bahwa tampilan di aplikasi menggunakan nilai yang benar dalam atribut android:autofillHints . Untuk daftar nilai yang dimungkinkan untuk atribut, lihat konstanta yang diawali dengan AUTOFILL_HINT dalam class View.
  • Periksa apakah atribut android:importantForAutofill disetel ke nilai selain no pada tampilan yang harus diisi, atau disetel ke nilai selain noExcludeDescendants pada tampilan atau salah satu induknya.