Dukungan keyboard gambar

Pengguna sering kali ingin berkomunikasi menggunakan emoji, stiker, dan jenis multimedia lainnya saat ini. Di versi Android sebelumnya, {i>soft keyboard<i}—juga dikenal sebagai editor metode input, atau IME—hanya dapat mengirim emoji Unicode ke aplikasi. Untuk konten lengkap, aplikasi yang dibangun API khusus aplikasi yang tidak dapat digunakan di aplikasi lain atau menggunakan solusi seperti mengirim gambar melalui tindakan berbagi sederhana atau papan klip.

Gambar yang menampilkan keyboard yang mendukung penelusuran gambar
Gambar 1. Contoh dukungan keyboard gambar.

Mulai Android 7.1 (API level 25), Android SDK menyertakan Commit Content API, yang menyediakan cara universal bagi IME untuk mengirim gambar dan konten lengkap langsung ke editor teks dalam sebuah aplikasi. API ini juga tersedia di Pustaka Dukungan v13 sejak revisi 25.0.0. Sebaiknya gunakan fitur Dukungan Library karena berisi metode bantuan yang menyederhanakan implementasi.

Dengan API ini, Anda dapat membangun aplikasi pesan yang menerima konten lengkap dari {i>keyboard<i} serta {i>keyboard<i} yang dapat mengirim konten lengkap ke aplikasi apa pun. Kebijakan Google Keyboard dan aplikasi seperti Message by Google mendukung Commit Content API di Android 7.1, seperti ditunjukkan dalam gambar 1.

Dokumen ini menunjukkan cara menerapkan Commit Content API di IME dan aplikasi.

Cara kerjanya

Penyisipan gambar keyboard memerlukan partisipasi dari IME dan aplikasi. Tujuan berikut menjelaskan setiap langkah dalam proses penyisipan gambar:

  1. Saat pengguna mengetuk EditText, editor mengirimkan daftar jenis konten MIME yang diterima di EditorInfo.contentMimeTypes.

  2. IME membaca daftar jenis yang didukung dan menampilkan konten di keyboard virtual yang dapat diterima oleh editor.

  3. Saat pengguna memilih gambar, IME akan memanggil commitContent() dan mengirimkan InputContentInfo ke editor. Panggilan commitContent() setara dengan Panggilan commitText(), tetapi untuk konten lengkap. InputContentInfo berisi URI yang mengidentifikasi konten dalam konten penyedia layanan.

Proses ini digambarkan dalam gambar 2:

Gambar yang menunjukkan urutan dari Application ke IME dan kembali ke Application
Gambar 2. Alur penerapan ke IME ke aplikasi.

Menambahkan dukungan gambar ke aplikasi

Untuk menerima konten lengkap dari IME, aplikasi harus memberi tahu IME konten apa yang jenisnya menerima dan menetapkan metode callback yang dijalankan ketika isi diterima. Contoh berikut menunjukkan cara membuat EditText yang menerima PNG gambar:

Kotlin

var editText: EditText = object : EditText(this) {
    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
        var ic = super.onCreateInputConnection(outAttrs)
        EditorInfoCompat.setContentMimeTypes(outAttrs, arrayOf("image/png"))
        val mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this)
        if (mimeTypes != null) {
            EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes)
            ic = InputConnectionCompat.createWrapper(this, ic, outAttrs)
        }
        return ic
    }
}

Java

EditText editText = new EditText(this) {
    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection ic = super.onCreateInputConnection(outAttrs);
        EditorInfoCompat.setContentMimeTypes(outAttrs, new String[]{"image/png"});
        String[] mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this);
        if (mimeTypes != null) {
            EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes);
            ic = InputConnectionCompat.createWrapper(this, ic, outAttrs);
        }
        return ic;
    }
};

Berikut adalah penjelasan lebih lanjut:

Berikut adalah praktik yang direkomendasikan:

  • Editor yang tidak mendukung konten lengkap tidak memanggil setContentMimeTypes(), dan keluar dari kumpulan EditorInfo.contentMimeTypes ke null.

  • Editor mengabaikan konten jika jenis MIME yang ditentukan dalam InputContentInfo tidak sesuai dengan tipe apa pun yang mereka terima.

  • Konten lengkap tidak terpengaruh dan tidak terpengaruh oleh posisi teks kursor. Editor dapat mengabaikan posisi kursor saat mengerjakan konten.

  • Di OnCommitContentListener.onCommitContent(), Anda dapat menampilkan true secara asinkron, bahkan sebelum memuat konten.

  • Tidak seperti teks yang dapat diedit di IME sebelum di-commit, konten akan segera di-commit. Jika Anda ingin mengizinkan pengguna mengedit atau menghapus konten lain, terapkan logikanya sendiri.

Untuk menguji aplikasi, pastikan perangkat atau emulator memiliki keyboard yang dapat mengirim konten lengkap. Anda dapat menggunakan Keyboard Google di Android 7.1 atau yang lebih baru.

Menambahkan dukungan gambar ke IME

IME yang ingin mengirim konten lengkap ke aplikasi harus menerapkan Konten Commit seperti yang ditunjukkan dalam contoh berikut:

  • Ganti onStartInput() atau onStartInputView() dan baca daftar jenis konten yang didukung dari target . Cuplikan kode berikut menunjukkan cara memeriksa apakah editor target menerima gambar GIF.

Kotlin

override fun onStartInputView(editorInfo: EditorInfo, restarting: Boolean) {
    val mimeTypes: Array<String> = EditorInfoCompat.getContentMimeTypes(editorInfo)

    val gifSupported: Boolean = mimeTypes.any {
        ClipDescription.compareMimeTypes(it, "image/gif")
    }

    if (gifSupported) {
        // The target editor supports GIFs. Enable the corresponding content.
    } else {
        // The target editor doesn't support GIFs. Disable the corresponding
        // content.
    }
}

Java

@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
    String[] mimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo);

    boolean gifSupported = false;
    for (String mimeType : mimeTypes) {
        if (ClipDescription.compareMimeTypes(mimeType, "image/gif")) {
            gifSupported = true;
        }
    }

    if (gifSupported) {
        // The target editor supports GIFs. Enable the corresponding content.
    } else {
        // The target editor doesn't support GIFs. Disable the corresponding
        // content.
    }
}
  • Commit konten ke aplikasi saat pengguna memilih gambar. Hindari menelepon commitContent() saat ada teks yang sedang ditulis, karena hal ini dapat menyebabkan editor kehilangan fokus. Cuplikan kode berikut menunjukkan cara untuk melakukan commit untuk gambar GIF.

Kotlin

// Commits a GIF image.

// @param contentUri = Content URI of the GIF image to be sent.
// @param imageDescription = Description of the GIF image to be sent.

fun commitGifImage(contentUri: Uri, imageDescription: String) {
    val inputContentInfo = InputContentInfoCompat(
            contentUri,
            ClipDescription(imageDescription, arrayOf("image/gif")),
            null
    )
    val inputConnection = currentInputConnection
    val editorInfo = currentInputEditorInfo
    var flags = 0
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        flags = flags or InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION
    }
    InputConnectionCompat.commitContent(inputConnection, editorInfo, inputContentInfo, flags, null)
}

Java

// Commits a GIF image.

// @param contentUri = Content URI of the GIF image to be sent.
// @param imageDescription = Description of the GIF image to be sent.

public static void commitGifImage(Uri contentUri, String imageDescription) {
    InputContentInfoCompat inputContentInfo = new InputContentInfoCompat(
            contentUri,
            new ClipDescription(imageDescription, new String[]{"image/gif"}),
            null
    );
    InputConnection inputConnection = getCurrentInputConnection();
    EditorInfo editorInfo = getCurrentInputEditorInfo();
    Int flags = 0;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        flags |= InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION;
    }
    InputConnectionCompat.commitContent(
            inputConnection, editorInfo, inputContentInfo, flags, null);
}

Sebagai penulis IME, Anda kemungkinan besar harus mengimplementasikan penyedia konten Anda sendiri untuk merespons permintaan URI konten. Pengecualiannya adalah jika IME Anda mendukung konten dari penyedia konten yang ada seperti MediaStore Untuk mengetahui informasi tentang membangun penyedia konten, lihat konten penyedia dan file penyedia layanan.

Jika Anda membuat penyedia konten sendiri, sebaiknya jangan mengekspornya berdasarkan setelan android:exported ke false. Sebagai gantinya, aktifkan pemberian izin di penyedia dengan mengatur android:grantUriPermission ke true. Kemudian, IME Anda dapat memberikan izin untuk mengakses URI konten ketika konten tersebut di-commit. Ada 2 cara untuk melakukannya:

  • Pada Android 7.1 (API level 25) dan yang lebih tinggi, saat memanggil commitContent(), setel parameter flag ke INPUT_CONTENT_GRANT_READ_URI_PERMISSION. Kemudian, objek InputContentInfo yang diterima aplikasi dapat meminta dan melepaskan izin baca sementara dengan memanggil requestPermission() dan releasePermission().

  • Pada Android 7.0 (level API 24) dan yang lebih rendah, INPUT_CONTENT_GRANT_READ_URI_PERMISSION diabaikan, jadi berikan secara manual izin akses ke konten tersebut. Salah satu cara untuk melakukannya adalah dengan grantUriPermission(), tetapi Anda dapat menerapkan mekanisme sendiri yang memenuhi persyaratan Anda sendiri.

Untuk menguji IME, pastikan perangkat atau emulator memiliki aplikasi yang dapat menerima konten lengkap. Anda dapat menggunakan aplikasi Google Messenger di Android 7.1 atau yang lebih baru.