Menerima konten lengkap

Gambar 1. API terpadu menyediakan satu tempat untuk menangani konten yang masuk terlepas dari mekanisme UI tertentu, seperti menempelkan dari sentuhan & tahan menu atau menggunakan tarik lalu lepas.

Pengguna menyukai gambar, video, dan konten ekspresif lainnya, tetapi memindahkan konten ini dalam aplikasi bukanlah hal yang mudah. Untuk mempermudah aplikasi untuk Android 12 (API level 31) memperkenalkan API terpadu yang memungkinkan aplikasi Anda menerima konten dari sumber apa pun: papan klip, keyboard, atau tarik.

Anda dapat melampirkan antarmuka, seperti OnReceiveContentListener, ke komponen UI dan mendapatkan callback saat konten disisipkan melalui mekanisme atensi. 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 menerapkan fungsi ini.

Ringkasan

Dengan API lain yang sudah ada, setiap mekanisme UI—seperti sentuhan & tahan menu atau menarik—memiliki API yang sesuai. Artinya, Anda harus berintegrasi dengan setiap API secara terpisah, menambahkan kode serupa untuk setiap mekanisme yang menyisipkan konten:

Gambar yang menunjukkan berbagai tindakan dan API relatif yang akan diimplementasikan
Gambar 2. Sebelumnya, aplikasi mengimplementasikan API yang berbeda untuk setiap UI mekanisme untuk 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:

Gambar yang menunjukkan API terpadu yang disederhanakan
Gambar 3. API terpadu memungkinkan Anda menerapkan satu API yang mendukung semua mekanisme UI.

Pendekatan ini juga berarti bahwa ketika cara baru untuk menyisipkan konten ditambahkan ke sehingga Anda tidak perlu membuat perubahan kode tambahan untuk mengaktifkan dukungan dalam aplikasi Anda. Dan jika aplikasi Anda perlu mengimplementasikan penyesuaian penuh untuk kasus penggunaan tertentu, Anda masih bisa menggunakan API yang sudah ada, yang akan 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, implementasikan pemroses dengan menentukan jenis konten aplikasi tersebut dapat menangani:

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) {
         Pair<ContentInfoCompat, ContentInfoCompat> split = 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 bisa 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. Sebagai pemrosesan yang berjalan lama, gunakan WorkManager. Saat Anda menerapkan ini, memperluas 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 diterima oleh pemroses untuk membantu memastikan bahwa tidak ada izin dicabut sebelum waktunya oleh platform.

Tampilan kustom

Jika aplikasi Anda menggunakan subclass View kustom, berhati-hatilah untuk memastikan bahwa OnReceiveContentListener tidak diabaikan.

Jika class View Anda menggantikan metode onCreateInputConnection, gunakan Jetpack API InputConnectionCompat.createWrapper untuk mengonfigurasi InputConnection.

Jika class View Anda mengganti onTextContextMenuItem , delegasikan ke super bila 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.

Tabel 1. Fitur dan level API yang didukung untuk Jetpack.
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)
Sisipkan menggunakan tempel dari sentuhan & tahan menu Tidak Ya
Sisipkan menggunakan tarik lalu lepas Tidak Ya (API level 24 dan yang lebih tinggi)
Tabel 2. Fitur dan API level yang didukung untuk native API.
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)
Sisipkan menggunakan tempel dari sentuhan & tahan menu Tidak
Sisipkan menggunakan tarik lalu lepas Tidak