Mengoptimalkan aplikasi Anda untuk isi otomatis

Aplikasi yang menggunakan tampilan standar berfungsi dengan Framework IsiOtomatis tanpa memerlukan konfigurasi khusus. Namun, Anda 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 pada perangkat agar aplikasi Anda dapat menggunakan Framework IsiOtomatis. Meskipun sebagian besar ponsel dan tablet yang menjalankan Android 8.0 (API level 26) dan yang lebih tinggi sudah dilengkapi dengan layanan isi otomatis, sebaiknya gunakan layanan pengujian saat menguji aplikasi, seperti layanan isi otomatis dalam contoh Framework IsiOtomatis Android Java | Kotlin Saat menggunakan emulator, Anda harus secara eksplisit menyetel layanan isi otomatis 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 informasi selengkapnya tentang cara mengonfigurasi emulator untuk menguji isi otomatis, baca Menguji aplikasi Anda dengan isi otomatis.

Memberikan petunjuk untuk isi otomatis

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

Anda dapat menyetel petunjuk ini menggunakan atribut android:autofillHints. Contoh berikut menyetel petunjuk "sandi" 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);

Konstanta petunjuk yang telah ditentukan sebelumnya

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

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

Kredensial akun

Saat melakukan isi otomatis untuk kredensial akun, formulir login mungkin berisi petunjuk seperti AUTOFILL_HINT_USERNAME dan AUTOFILL_HINT_PASSWORD.

Saat 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 kode berikut:

Alamat fisik

Saat melakukan isi otomatis alamat fisik, Anda dapat menggunakan petunjuk seperti berikut:

Nama orang

Saat melakukan isi otomatis 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 tampilan tunggal, Anda dapat menggunakan AUTOFILL_HINT_SMS_OTP.

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

Menandai kolom sebagai penting untuk isi otomatis

Anda dapat memberi tahu sistem apakah kolom individual di aplikasi Anda harus disertakan 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 tersebut penting untuk isi otomatis.

Anda dapat menyetel nilai penting menggunakan atribut android:importantForAutofill:

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

Nilai importantForAutofill dapat berupa nilai apa pun yang ditentukan dalam android:importantForAutofill:

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

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

  • Kolom CAPTCHA dalam aktivitas login biasanya tidak penting untuk isi otomatis. Pada kasus seperti ini, Anda dapat menandai tampilan sebagai IMPORTANT_FOR_AUTOFILL_NO.
  • Dalam tampilan saat pengguna membuat konten, seperti editor teks atau spreadsheet, keseluruhan struktur tampilan biasanya tidak penting untuk isi otomatis. Pada kasus seperti ini, Anda dapat menandai tampilan sebagai IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS untuk memastikan semua turunan juga ditandai sebagai tidak penting untuk isi otomatis.
  • Pada beberapa aktivitas dalam game, seperti game yang menampilkan alur game, tidak satu pun tampilan dalam aktivitas tersebut yang penting untuk isi otomatis. Anda dapat menandai tampilan root sebagai IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS untuk memastikan semua tampilan dalam aktivitas ditandai sebagai tidak penting untuk isi otomatis.

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, Anda harus meng-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

Anda dapat menerapkan fungsi isi otomatis tambahan di aplikasi, atau bahkan di tampilan tertentu pada aplikasi, jika fitur 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() objekAutofillManager.

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.

Untuk memastikan pengalaman pendaftaran dan login yang optimal bagi pengguna tanpa fitur isi otomatis, pertimbangkan untuk menerapkan Smart Lock untuk Sandi.

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 jika pengguna menekan 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. Hal ini dapat berguna, misalnya, jika Anda memiliki tombol yang menghapus kolom pada halaman login.

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

Alat pilih berguna dalam beberapa skenario isi otomatis dengan menyediakan UI yang memungkinkan pengguna mengubah nilai kolom yang menyimpan data tanggal atau waktu. Misalnya, dalam formulir kartu kredit, alat pilih 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 memperkirakan 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 informasi selengkapnya, lihat Menggunakan alat pilih dengan isi otomatis.

Menyelesaikan konteks isi otomatis

Framework IsiOtomatis akan menyimpan input pengguna untuk penggunaan mendatang dengan menampilkan dialog "Simpan untuk isi otomatis?" setelah konteks isi otomatisisi 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 IsiOtomatis 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 IsiOtomatis.

Jika aplikasi Anda menggunakan tampilan kustom, Anda harus mempertimbangkan 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 IsiOtomatis.

Tampilan kustom dengan struktur tampilan standar

Tampilan kustom dapat menentukan metadata yang diperlukan isi otomatis agar berfungsi. Anda harus memastikan bahwa tampilan kustom mengelola metadata secara tepat agar berfungsi dengan Framework IsiOtomatis. 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 IsiOtomatis akan memanggil autofill() pada tampilan dan mengirimkan nilai yang akan digunakan tampilan Anda. Anda harus mengimplementasikan 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(). Dengan menambahkan kode ini, Anda memastikan bahwa tampilan dapat memberikan jenis dan nilai isi otomatis yang sesuai ke framework.

Terakhir, isi otomatis tidak boleh mengisi tampilan jika pengguna tidak dapat memberikan nilai untuk tampilan dalam status saat ini (misalnya, jika tampilan dinonaktifkan). Pada kasus ini, getAutofillType() harus mengembalikan AUTOFILL_TYPE_NONE, getAutofillValue() harus mengembalikan null, dan autofill() harus tidak 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, Anda harus memberi tahu Framework IsiOtomatis tentang perubahan dengan memanggil objek notifyValueChanged() pada AutofillManager.

Tampilan kustom berisi data sensitif

Jika tampilan berisi informasi identitas pribadi (PII), seperti alamat email, nomor kartu kredit, dan sandi, tampilan harus ditandai sebagai demikian. Secara umum, tampilan yang kontennya berasal dari resource statis tidak berisi data sensitif, tetapi tampilan yang kontennya disetel secara dinamis dapat berisi data sensitif. Misalnya, label yang berisi masukkan nama pengguna tidak berisi data sensitif, sedangkan label yang berisi Halo, John berisi data sensitif. Untuk menandai apakah tampilan berisi data sensitif atau tidak, terapkan onProvideAutofillStructure() dan panggil setDataIsSensitive() pada objek ViewStructure.

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

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

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. Namun, jika Anda memberikan nilai secara dinamis, Anda harus mengganti getAutofillOptions().

Tampilan kustom dengan struktur virtual

Framework IsiOtomatis memerlukan struktur tampilan agar dapat mengedit dan menyimpan informasi di UI aplikasi. Ada beberapa situasi saat struktur tampilan tidak tersedia untuk framework:

  • 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, Anda harus meneruskan true ke setDataIsSensitive() atau 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. 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);
}

Saat elemen dalam struktur virtual berubah, Anda harus memberi tahu framework tersebut dengan melakukan 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 telah menyelesaikan langkah dalam alur kerja (misalnya, pengguna yang login menggunakan formulir login), panggil commit() pada objek AutofillManager.
  • Jika hierarki tampilan tidak valid lagi karena pengguna telah membatalkan langkah dalam alur kerja (misalnya, jika pengguna mengklik 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 IsiOtomatis 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 di-isi otomatis, platform akan me-render Drawable pada tampilan untuk menunjukkan konten tampilan telah di-isi 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 cara aplikasi berperilaku saat 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, sangat 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 diisi, layanan isi otomatis akan mempertahankan makna logis tampilan menggunakan ID isi otomatisnya. Karena sistem menggunakan kembali tampilan dalam tata letak, masalah akan terjadi bila, ID logis tampilan tetap sama, menyebabkan isi otomatis data pengguna yang salah yang dikaitkan dengan ID isi otomatis.

Untuk mengatasi masalah ini di perangkat yang menjalankan Android 9 (API level 28) dan yang lebih tinggi, Anda dapat secara eksplisit mengelola tampilan ID isi otomatis yang digunakan oleh RecyclerView menggunakan metode baru 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 IsiOtomatis.

Isi otomatis menyebabkan aplikasi error pada Android 8.0, 8.1

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

Dialog yang diubah ukurannya tidak dipertimbangkan untuk isi otomatis

Di Android 8.1 (API level 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, 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();
    }
}

Menguji aplikasi Anda dengan isi otomatis

Sebagian besar aplikasi berfungsi dengan layanan isi otomatis tanpa perubahan apa pun. Namun, Anda dapat mengoptimalkan aplikasi untuk memastikannya berfungsi sebaik mungkin dengan layanan isi otomatis. Setelah mengoptimalkan aplikasi, Anda harus mengujinya untuk memastikan aplikasi berfungsi dengan layanan isi otomatis seperti yang diharapkan.

Anda harus menggunakan emulator atau perangkat fisik yang menjalankan Android 8.0 (API level 26) atau yang lebih tinggi untuk menguji aplikasi. Untuk 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 mana pun.

Anda dapat menggunakan contoh Framework IsiOtomatis Android Java | Kotlin untuk menguji aplikasi Anda 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 menginstal aplikasi, Anda harus mengaktifkan layanan isi otomatis di setelan sistem. Anda dapat mengaktifkan layanan 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.

Anda harus mengizinkan layanan mengetahui jenis data yang diminta 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

Langkah-langkah berikut menunjukkan cara menyimpan data di layanan isi otomatis yang sedang aktif:

  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. Ketik nilai ke dalam tampilan.
  4. Ketuk tombol konfirmasi, seperti Sign in atau Submit.

    Anda biasanya harus mengirimkan formulir sebelum layanan mencoba menyimpan data.

  5. Sistem akan menampilkan dialog yang meminta izin untuk menyimpan data. Dialog akan menampilkan nama layanan yang sedang aktif.

    Verifikasi bahwa ini adalah layanan yang ingin Anda gunakan dalam pengujian, lalu 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

Langkah-langkah berikut menunjukkan cara memicu isi otomatis di aplikasi:

  1. Buka aplikasi, lalu buka aktivitas yang memiliki tampilan yang ingin diuji.
  2. Ketuk tampilan yang harus 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 yang berisi data yang ingin Anda gunakan. Tampilan akan 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.