Użytkownicy uwielbiają obrazy, filmy i inne ekspresyjne treści, ale umieszczanie ich w aplikacjach i przenoszenie ich w aplikacjach nie zawsze jest łatwe. Aby ułatwić aplikacjom otrzymywanie szczegółowych treści, Android 12 (poziom interfejsu API 31) wprowadza ujednolicony interfejs API, który pozwala aplikacji akceptować treści z dowolnego źródła: ze schowka, klawiatury czy przeciągania.
Do komponentów UI możesz dołączyć interfejs, na przykład OnReceiveContentListener
, i otrzymać wywołanie zwrotne, gdy treść zostanie wstawiona za pomocą dowolnego mechanizmu. Wywołanie zwrotne staje się jedynym miejscem, w którym kod może odbierać wszystkie treści – od zwykłego tekstu i ze stylem 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 od Core 1.7 do Appcompat 1.4. Zalecamy korzystanie z tej funkcji podczas wdrażania tej funkcji.
Przegląd
W przypadku innych istniejących interfejsów API każdy mechanizm interfejsu – np. menu dotknięcia i przytrzymania czy przeciąganie – ma własny interfejs API. Oznacza to, że musisz przeprowadzić integrację z każdym interfejsem API oddzielnie, dodając podobny kod dla każdego mechanizmu, który wstawia treść:
Interfejs OnReceiveContentListener
API konsoliduje różne ścieżki kodu, tworząc pojedynczy interfejs API do zaimplementowania. Dzięki temu możesz skupić się na logice związanej z aplikacją, a platformę obsługiwać resztę:
Oznacza to również, że gdy dodasz do platformy nowe sposoby wstawiania treści, nie musisz wprowadzać dodatkowych zmian w kodzie, aby włączyć obsługę aplikacji. 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 nadal działają w ten sam sposób.
Implementacja
Interfejs API to interfejs nasłuchującego z pojedynczą metodą – OnReceiveContentListener
.
Aby obsługiwać starsze wersje platformy Androida, zalecamy skorzystanie z pasującego interfejsu OnReceiveContentListener
w bibliotece AndroidX Core.
Aby użyć tego interfejsu API, zaimplementuj detektor, 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 Twoją aplikację zaimplementuj 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) { 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; } }
Jeśli Twoja aplikacja obsługuje już udostępnianie z intencjami, możesz ponownie użyć logiki aplikacji do obsługi identyfikatorów URI treści. Zwróć pozostałe dane, aby przekazać obsługę tych danych na platformie.
Po zaimplementowaniu detektora ustaw go w odpowiednich elementach interfejsu 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 uprawnienia do odczytu w przypadku wszystkich identyfikatorów URI treści w ładunku przekazanym do OnReceiveContentListener
.
Normalnie aplikacja przetwarza identyfikatory URI treści w usłudze lub działaniu. Do długotrwałego przetwarzania użyj WorkManagera. Jeśli to zrobisz, rozszerz uprawnienia docelowej usługi lub aktywności, przekazując treści za pomocą Intent.setClipData
i ustawiając flagę FLAG_GRANT_READ_URI_PERMISSION
.
Do przetwarzania treści możesz też użyć wątku w tle w bieżącym kontekście. W takim przypadku musisz utrzymywać odniesienie do obiektu payload
otrzymanego przez detektor, aby zapobiec przedwczesnemu unieważnieniu uprawnień przez platformę.
Widoki niestandardowe
Jeśli Twoja aplikacja używa niestandardowej podklasy View
, upewnij się, że nie jest pomijana klasy OnReceiveContentListener
.
Jeśli klasa View
zastępuje metodę onCreateInputConnection
, użyj interfejsu Jetpack API InputConnectionCompat.createWrapper
, aby skonfigurować InputConnection
.
Jeśli klasa View
zastępuje metodę onTextContextMenuItem
, przekaż dostęp do super, gdy element menu to R.id.paste
lub R.id.pasteAsPlainText
.
Porównanie z interfejsem API obrazu klawiatury
Interfejs OnReceiveContentListener
API możesz traktować jako nową wersję istniejącego interfejsu Keyboard Image API. Ten ujednolicony interfejs API obsługuje funkcje interfejsu API obrazu klawiatury, a także kilka dodatkowych funkcji. Zgodność urządzenia i funkcji różni się w zależności od tego, czy używasz biblioteki Jetpack, czy natywnych interfejsów API z pakietu Android SDK.
Działanie lub funkcja | Obsługiwany przez interfejs API grafiki klawiatury | 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 naciskając i przytrzymując | Nie | Tak |
Wstawianie za pomocą przeciągania i upuszczania | Nie | Tak (poziom API 24 lub wyższy) |
Działanie lub funkcja | Obsługiwany przez interfejs API grafiki klawiatury | 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 naciskając i przytrzymując | Nie | |
Wstaw za pomocą przeciągania i upuszczania | Nie |