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.
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:
Saat pengguna mengetuk
EditText
, editor 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()
setara dengan PanggilancommitText()
, tetapi untuk konten lengkap.InputContentInfo
berisi URI yang mengidentifikasi konten dalam konten penyedia layanan.
Proses ini digambarkan dalam gambar 2:
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:
Contoh ini menggunakan {i>Support Library<i}, jadi ada beberapa referensi untuk
android.support.v13.view.inputmethod
bukannyaandroid.view.inputmethod
.Contoh ini membuat
EditText
dan menggantikannyaonCreateInputConnection(EditorInfo)
untuk memodifikasiInputConnection
.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()
akan menambahkan daftar jenis MIME yang didukung keEditorInfo
. Teleponsuper.onCreateInputConnection()
sebelumsetContentMimeTypes()
.callback
dieksekusi setiap kali IME meng-commit konten. MetodeonCommitContent()
memiliki referensi keInputContentInfoCompat
, yang berisi URI konten.- Meminta dan merilis izin jika aplikasi Anda berjalan di API level 25
atau yang lebih tinggi dan
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
penanda yang ditetapkan oleh IME. Jika tidak, Anda sudah memiliki akses ke konten URI karena telah diberikan oleh IME atau karena penyedia konten tidak membatasi akses. Untuk informasi selengkapnya, lihat Menambahkan dukungan gambar ke IME.
- Meminta dan merilis izin jika aplikasi Anda berjalan di API level 25
atau yang lebih tinggi dan
createWrapper()
menggabungkanInputConnection
,EditorInfo
yang diubah, dan callback menjadiInputConnection
baru dan menampilkannya.
Berikut adalah praktik yang direkomendasikan:
Editor yang tidak mendukung konten lengkap tidak memanggil
setContentMimeTypes()
, dan keluar dari kumpulanEditorInfo.contentMimeTypes
kenull
.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 menampilkantrue
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()
atauonStartInputView()
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 keINPUT_CONTENT_GRANT_READ_URI_PERMISSION
. Kemudian, objekInputContentInfo
yang diterima aplikasi dapat meminta dan melepaskan izin baca sementara dengan memanggilrequestPermission()
danreleasePermission()
.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 dengangrantUriPermission()
, 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.