Dukungan keyboard gambar

Pengguna sering kali ingin berkomunikasi menggunakan emoji, stiker, dan jenis konten lengkap lainnya. Pada Android versi sebelumnya, keyboard virtual—juga dikenal sebagai editor metode input, atau IME—hanya dapat mengirim emoji Unicode ke aplikasi. Untuk konten lengkap, aplikasi membuat 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 menunjukkan keyboard yang mendukung penelusuran gambar
Gambar 1. Contoh dukungan keyboard gambar.

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

Dengan API ini, Anda dapat membuat aplikasi pesan yang menerima konten lengkap dari keyboard apa pun serta keyboard yang dapat mengirim konten lengkap ke aplikasi apa pun. Keyboard Google 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 kerja

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

  1. Saat pengguna mengetuk EditText, editor akan 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() serupa dengan panggilan commitText(), tetapi untuk konten lengkap. InputContentInfo berisi URI yang mengidentifikasi konten di penyedia konten.

Proses ini digambarkan dalam gambar 2:

Gambar yang menunjukkan urutan dari Aplikasi ke IME dan kembali ke Aplikasi
Gambar 2. Penerapan ke IME ke alur aplikasi.

Menambahkan dukungan gambar ke aplikasi

Untuk menerima konten lengkap dari IME, aplikasi harus memberi tahu IME konten jenis apa yang diterima dan menentukan metode callback yang dieksekusi saat konten diterima. Contoh berikut menunjukkan cara membuat EditText yang menerima gambar PNG:

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 akan memanggil setContentMimeTypes(), dan mereka membiarkan EditorInfo.contentMimeTypes disetel ke null.

  • Editor mengabaikan konten jika jenis MIME yang ditentukan dalam InputContentInfo tidak cocok dengan jenis apa pun yang diterima.

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

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

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

Untuk menguji aplikasi, pastikan perangkat atau emulator Anda 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 Commit Content API, seperti yang ditunjukkan dalam contoh berikut:

  • Ganti onStartInput() atau onStartInputView() dan baca daftar jenis konten yang didukung dari editor 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 memanggil commitContent() jika ada teks yang ditulis, karena dapat menyebabkan editor kehilangan fokus. Cuplikan kode berikut menunjukkan cara meng-commit 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 mungkin harus menerapkan penyedia konten sendiri untuk merespons permintaan URI konten. Pengecualiannya adalah jika IME Anda mendukung konten dari penyedia konten yang ada seperti MediaStore. Untuk mengetahui informasi tentang cara membangun penyedia konten, lihat dokumentasi penyedia konten dan penyedia file.

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

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

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

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