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.
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:
Saat pengguna mengetuk
EditText
, editor akan mengirimkan daftar jenis konten MIME yang diterima diEditorInfo.contentMimeTypes
.IME membaca daftar jenis yang didukung dan menampilkan konten di keyboard virtual yang dapat diterima oleh editor.
Saat pengguna memilih gambar, IME akan memanggil
commitContent()
dan mengirimkanInputContentInfo
ke editor. PanggilancommitContent()
serupa dengan panggilancommitText()
, tetapi untuk konten lengkap.InputContentInfo
berisi URI yang mengidentifikasi konten di penyedia konten.
Proses ini digambarkan dalam gambar 2:
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:
Contoh ini menggunakan Support Library, sehingga ada beberapa referensi ke
android.support.v13.view.inputmethod
, bukanandroid.view.inputmethod
.Contoh ini membuat
EditText
dan mengganti metodeonCreateInputConnection(EditorInfo)
untuk mengubahInputConnection
.InputConnection
adalah saluran komunikasi antara IME dan aplikasi yang menerima inputnya.Panggilan
super.onCreateInputConnection()
mempertahankan perilaku bawaan—mengirim dan menerima teks—dan memberi Anda referensi keInputConnection
.setContentMimeTypes()
menambahkan daftar jenis MIME yang didukung keEditorInfo
. Panggilsuper.onCreateInputConnection()
sebelumsetContentMimeTypes()
.callback
dieksekusi setiap kali IME meng-commit konten. MetodeonCommitContent()
memiliki referensi keInputContentInfoCompat
, yang berisi URI konten.- Minta dan rilis izin jika aplikasi Anda berjalan di API level 25
atau yang lebih tinggi dan flag
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
ditetapkan oleh IME. Jika tidak, Anda sudah memiliki akses ke URI konten karena diberikan oleh IME atau karena penyedia konten tidak membatasi akses. Untuk mengetahui informasi selengkapnya, lihat Menambahkan dukungan gambar ke IME.
- Minta dan rilis izin jika aplikasi Anda berjalan di API level 25
atau yang lebih tinggi dan flag
createWrapper()
menggabungkanInputConnection
,EditorInfo
yang dimodifikasi, dan callback ke dalamInputConnection
baru dan menampilkannya.
Berikut adalah praktik yang direkomendasikan:
Editor yang tidak mendukung konten lengkap tidak akan memanggil
setContentMimeTypes()
, dan mereka membiarkanEditorInfo.contentMimeTypes
disetel kenull
.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 menampilkantrue
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()
atauonStartInputView()
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 keINPUT_CONTENT_GRANT_READ_URI_PERMISSION
. Kemudian, objekInputContentInfo
yang diterima aplikasi dapat meminta dan merilis izin baca sementara dengan memanggilrequestPermission()
danreleasePermission()
.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 dengangrantUriPermission()
, 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.