Pengguna menyukai gambar, video, dan konten ekspresif lainnya, tetapi memasukkan dan memindahkan konten ini di aplikasi tidaklah selalu mudah. Untuk memudahkan aplikasi menerima konten lengkap, Android 12 (API level 31) memperkenalkan API terpadu yang memungkinkan aplikasi Anda menerima konten dari sumber mana pun: papan klip, keyboard, atau penarikan.
Anda dapat melampirkan antarmuka, seperti
OnReceiveContentListener
,
ke komponen UI dan mendapatkan callback saat konten disisipkan melalui mekanisme
apa pun. Callback menjadi satu tempat bagi kode Anda untuk menangani
penerimaan semua konten, dari teks biasa dan bergaya hingga markup, gambar, video,
file audio, dan lainnya.
Untuk kompatibilitas mundur dengan versi Android sebelumnya, API ini juga tersedia di AndroidX, mulai dari Core 1.7 dan Appcompat 1.4, yang sebaiknya Anda gunakan saat mengimplementasikan fungsi ini.
Ringkasan
Dengan API yang ada, setiap mekanisme UI—seperti menu sentuh lama atau menarik—memiliki API yang sesuai. Artinya, Anda harus berintegrasi dengan setiap API secara terpisah, menambahkan kode serupa untuk setiap mekanisme yang menyisipkan konten:
API OnReceiveContentListener
menggabungkan berbagai jalur kode dengan
membuat satu API untuk diterapkan, sehingga Anda dapat berfokus pada logika khusus aplikasi
dan memungkinkan platform menangani logika yang tersisa:
Pendekatan ini juga berarti bahwa saat cara baru menyisipkan konten ditambahkan ke platform, Anda tidak perlu melakukan perubahan kode tambahan untuk mengaktifkan dukungan di aplikasi. Dan jika aplikasi Anda perlu menerapkan penyesuaian penuh untuk kasus penggunaan tertentu, Anda masih dapat menggunakan API yang ada, yang terus berfungsi dengan cara yang sama.
Implementasi
API adalah antarmuka pemroses dengan satu metode,
OnReceiveContentListener
.
Untuk mendukung platform Android versi lama, sebaiknya gunakan
antarmuka
OnReceiveContentListener
yang cocok di library AndroidX Core.
Untuk menggunakan API, terapkan pemroses dengan menentukan jenis konten yang dapat ditangani oleh aplikasi Anda:
Kotlin
object MyReceiver : OnReceiveContentListener { val MIME_TYPES = arrayOf("image/*", "video/*") // ... override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? { TODO("Not yet implemented") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; // ... }
Setelah menentukan semua jenis MIME konten yang didukung oleh aplikasi, terapkan pemroses lainnya:
Kotlin
class MyReceiver : OnReceiveContentListener { override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat { val split = contentInfo.partition { item: ClipData.Item -> item.uri != null } val uriContent = split.first val remaining = split.second if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining } companion object { val MIME_TYPES = arrayOf("image/*", "video/*") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; @Override public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) { Pairsplit = contentInfo.partition( item -> item.getUri() != null); ContentInfo uriContent = split.first; ContentInfo remaining = split.second; if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining; } }
Jika aplikasi sudah mendukung berbagi dengan intent, Anda dapat menggunakan kembali logika khusus aplikasi untuk menangani URI konten. Tampilkan data yang tersisa untuk mendelegasikan penanganan data tersebut ke platform.
Setelah mengimplementasikan pemroses, tetapkan pada elemen UI yang sesuai di aplikasi Anda:
Kotlin
class MyActivity : Activity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... val myInput = findViewById(R.id.my_input) ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver()) } }
Java
public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { // ... AppCompatEditText myInput = findViewById(R.id.my_input); ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver()); } }
Izin URI
Izin baca diberikan dan dirilis secara otomatis oleh platform untuk setiap
URI konten dalam
payload yang diteruskan ke OnReceiveContentListener
.
Biasanya, aplikasi Anda memproses URI konten dalam layanan atau aktivitas. Untuk
pemrosesan yang berjalan lama, gunakan
WorkManager. Saat Anda menerapkan
hal ini, perluas izin ke layanan atau aktivitas target dengan meneruskan
konten menggunakan
Intent.setClipData
dan menetapkan flag
FLAG_GRANT_READ_URI_PERMISSION
.
Atau, Anda dapat menggunakan thread latar belakang dalam konteks saat ini untuk
memproses konten. Dalam hal ini, Anda harus mempertahankan referensi ke
objek payload
yang diterima oleh pemroses untuk membantu memastikan bahwa izin tidak
dicabut lebih awal oleh platform.
Tampilan kustom
Jika aplikasi Anda menggunakan subclass View
kustom, pastikan
OnReceiveContentListener
tidak diabaikan.
Jika class View
Anda menggantikan
metode onCreateInputConnection
,
gunakan Jetpack API
InputConnectionCompat.createWrapper
untuk mengonfigurasi InputConnection
.
Jika class View
Anda mengganti
metode onTextContextMenuItem
, delegasikan ke super saat item menu
R.id.paste
atau
R.id.pasteAsPlainText
.
Perbandingan dengan keyboard image API
Anda dapat menganggap API OnReceiveContentListener
sebagai versi API gambar keyboard
berikutnya. API terpadu ini
mendukung fungsi API gambar keyboard serta beberapa
fitur tambahan. Perangkat dan kompatibilitas fitur bervariasi bergantung pada
apakah Anda menggunakan library Jetpack atau API native dari Android SDK.
Tindakan atau fitur | Didukung oleh API image keyboard | Didukung oleh API terpadu |
---|---|---|
Sisipkan dari keyboard | Ya (API level 13 dan yang lebih tinggi) | Ya (API level 13 dan yang lebih tinggi) |
Menyisipkan menggunakan tempel dari menu sentuh lama | Tidak | Ya |
Sisipkan menggunakan tarik lalu lepas | Tidak | Ya (API level 24 dan yang lebih tinggi) |
Tindakan atau fitur | Didukung oleh API image keyboard | Didukung oleh API terpadu |
---|---|---|
Sisipkan dari keyboard | Ya (API level 25 dan yang lebih tinggi) | Ya (Android 12 dan yang lebih tinggi) |
Menyisipkan menggunakan tempel dari menu sentuh lama | Tidak | |
Sisipkan menggunakan tarik lalu lepas | Tidak |