Otrzymuj szczegółowe treści

Rys. 1. Ujednolicony interfejs API zapewnia jedno miejsce do obsługi przychodzących treści niezależnie od konkretnego mechanizmu interfejsu użytkownika, takiego jak wklejanie z menu dotknięcia i przytrzymania czy przeciąganie i upuszczanie.

Użytkownicy uwielbiają obrazy, filmy i inne ekspresyjne treści, ale wstawianie i przenoszenie tych treści w aplikacjach nie zawsze jest łatwe. Aby ułatwić aplikacjom odbieranie treści multimedialnych, Android 12 (poziom interfejsu API 31) wprowadza ujednolicony interfejs API, który pozwala aplikacjom akceptować treści z dowolnego źródła: schowka, klawiatury lub przeciągania.

Do komponentów interfejsu możesz podłączyć interfejs, np. OnReceiveContentListener, i otrzymywać wywołanie zwrotne, gdy treść zostanie wstawiona za pomocą dowolnego mechanizmu. Wywołanie zwrotne staje się miejscem, w którym Twój kod odbiera całą zawartość – od zwykłego i stylowanego tekstu po znaczniki, obrazy, filmy, pliki audio i inne.

Aby zapewnić zgodność wsteczną z poprzednimi wersjami Androida, ten interfejs API jest też dostępny w AndroidzieX, począwszy od Core 1.7 i Appcompat 1.4. Zalecamy korzystanie z niego przy implementowaniu tej funkcji.

Omówienie

W przypadku innych istniejących interfejsów API każdy mechanizm interfejsu – taki jak menu naciśnięcia i przytrzymania lub przeciągnięcie – ma swój własny interfejs API. Musisz więc zintegrować go z każdym interfejsem API oddzielnie, dodając podobny kod do każdego mechanizmu wstawiającego treści:

Obraz przedstawiający różne działania i względny interfejs API do wdrożenia
Rysunek 2. Wcześniej w przypadku każdego mechanizmu w interfejsie aplikacji stosowano inny interfejs API do wstawiania treści.

Interfejs API OnReceiveContentListener konsoliduje te różne ścieżki kodu, tworząc pojedynczy interfejs API do zaimplementowania, dzięki czemu możesz skupić się na logice konkretnej aplikacji, a platforma zajmie się resztą:

Obraz przedstawiający uproszczony ujednolicony interfejs API
Rysunek 3. Ujednolicony interfejs API umożliwia wdrożenie jednego interfejsu API, który obsługuje wszystkie mechanizmy interfejsu użytkownika.

Oznacza to również, że po dodaniu do platformy nowych sposobów wstawiania treści nie trzeba wprowadzać dodatkowych zmian w kodzie, aby zapewnić obsługę aplikacji. A jeśli aplikacja musi wdrożyć pełne dostosowanie do konkretnego przypadku użycia, możesz nadal korzystać z istniejących interfejsów API, które działają w ten sam sposób.

Implementacja

Interfejs API to interfejs detektora z pojedynczą metodą – OnReceiveContentListener. Do obsługi starszych wersji platformy Androida zalecamy używanie interfejsu dopasowywania OnReceiveContentListener z biblioteki AndroidX Core.

Aby korzystać z interfejsu API, zaimplementuj odbiornik, określając typy treści, które może obsługiwać aplikacja:

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/*"};
     // ...
}

Po określeniu wszystkich typów MIME treści obsługiwanych przez aplikację wdróż resztę detektora:

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 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;
     }
 }

Jeśli Twoja aplikacja obsługuje już udostępnianie za pomocą intencji, możesz ponownie wykorzystać logikę tej aplikacji do obsługi identyfikatorów URI treści. Zwróć pozostałe dane, aby przekazać obsługę ich do platformy.

Po zaimplementowaniu detektora ustaw go na odpowiednich elementach interfejsu w swojej aplikacji:

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());
     }
}

Uprawnienia dotyczące identyfikatora URI

Platforma automatycznie przyznaje i zwalnia do odczytu uprawnienia do odczytu dla wszystkich identyfikatorów URI treści w ładunku przekazywanym do OnReceiveContentListener.

Zwykle aplikacja przetwarza identyfikatory URI treści w usłudze lub działaniu. Jeśli chcesz przeprowadzać długotrwałe przetwarzanie, użyj WorkManagera. Podczas wdrażania tej opcji rozszerz uprawnienia do usługi docelowej lub działania, przekazując treść za pomocą polecenia Intent.setClipData i ustawiając flagę FLAG_GRANT_READ_URI_PERMISSION.

Do przetworzenia treści możesz też użyć wątku w tle w bieżącym kontekście. W takim przypadku musisz zachować odniesienie do obiektu payload otrzymanego przez detektor, aby mieć pewność, że uprawnienia nie zostaną przedwcześnie unieważnione przez platformę.

Widoki niestandardowe

Jeśli aplikacja używa niestandardowej podklasy View, upewnij się, że nie zostanie pominięta klasa OnReceiveContentListener.

Jeśli klasa View zastępuje metodę onCreateInputConnection, skonfiguruj InputConnection za pomocą interfejsu Jetpack API InputConnectionCompat.createWrapper.

Jeśli klasa View zastępuje metodę onTextContextMenuItem, przekaż działanie funkcji super, gdy pozycja menu to R.id.paste lub R.id.pasteAsPlainText.

Porównanie z interfejsem API Obraz klawiatury

Interfejs OnReceiveContentListener API to następna wersja istniejącego keyboard Image API. Ten ujednolicony interfejs API obsługuje funkcje Content API z obrazem klawiatury, a także kilka dodatkowych funkcji. Zgodność urządzeń i funkcji różni się w zależności od tego, czy korzystasz z biblioteki Jetpack czy natywnych interfejsów API z pakietu Android SDK.

Tabela 1. Obsługiwane funkcje i poziomy interfejsów API w Jetpack.
Działanie lub funkcja Obsługiwane przez interfejs klawiatury Image API Obsługiwane przez ujednolicony interfejs API
Wstawianie z klawiatury Tak (poziom API 13 lub wyższy) Tak (poziom API 13 lub wyższy)
Wstaw przez wklejenie z menu naciśnięcia i przytrzymania Nie Tak
Wstaw za pomocą przeciągania i upuszczania Nie Tak (poziom API 24 lub wyższy)
Tabela 2. Obsługiwane funkcje i poziomy interfejsów API dla natywnych interfejsów API.
Działanie lub funkcja Obsługiwane przez interfejs klawiatury Image API Obsługiwane przez ujednolicony interfejs API
Wstawianie z klawiatury Tak (poziom API 25 lub wyższy) Tak (Android 12 lub nowszy)
Wstaw przez wklejenie z menu naciśnięcia i przytrzymania Nie
Wstaw za pomocą przeciągania i upuszczania Nie