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 szczegółowych treści, w Androidzie 12 (poziom API 31) wprowadziliśmy ujednolicony interfejs API, który umożliwia aplikacji akceptowanie treści z dowolnego źródła: schowka, klawiatury lub przeciągania.
Możesz dołączyć interfejs, np.
OnReceiveContentListener,
do komponentów interfejsu użytkownika i otrzymywać wywołanie zwrotne, gdy treść zostanie wstawiona za pomocą dowolnego
mechanizmu. Wywołanie zwrotne staje się jednym miejscem, w którym Twój kod może obsługiwać odbieranie wszystkich treści – od zwykłego i sformatowanego 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 AndroidX, począwszy od Core 1.7 i Appcompat 1.4, Zalecamy używanie go podczas implementowania tej funkcji.
Przegląd
W przypadku innych istniejących interfejsów API każdy mechanizm interfejsu użytkownika, taki jak menu wyświetlane po naciśnięciu i przytrzymaniu lub przeciąganie, ma własny interfejs API. Oznacza to, że musisz zintegrować się z każdym interfejsem API osobno, dodając podobny kod dla każdego mechanizmu, który wstawia treści:
Interfejs API OnReceiveContentListener konsoliduje te różne ścieżki kodu, tworząc jeden interfejs API do implementacji, dzięki czemu możesz skupić się na logice specyficznej dla aplikacji, a resztę pozostawić platformie:
To podejście oznacza też, że gdy do platformy zostaną dodane nowe sposoby wstawiania treści, nie musisz wprowadzać dodatkowych zmian w kodzie, aby włączyć obsługę w aplikacji. Jeśli aplikacja wymaga pełnej personalizacji w określonym przypadku użycia, nadal możesz korzystać z dotychczasowych interfejsów API, które działają tak samo.
Implementacja
Interfejs API to interfejs odbiornika z jedną metodą,
OnReceiveContentListener.
Aby obsługiwać starsze wersje platformy Android, zalecamy używanie
pasującego
OnReceiveContentListener
interfejsu w bibliotece AndroidX Core.
Aby używać interfejsu API, zaimplementuj odbiornik, określając typy treści, które Twoja aplikacja może obsługiwać:
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, które obsługuje Twoja aplikacja, zaimplementuj pozostałą część odbiornika:
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; } }
Jeśli Twoja aplikacja obsługuje już udostępnianie za pomocą intencji, możesz ponownie wykorzystać logikę specyficzną dla aplikacji do obsługi identyfikatorów URI treści. Zwróć pozostałe dane, aby przekazać ich obsługę platformie.
Po zaimplementowaniu odbiornika ustaw go w odpowiednich elementach interfejsu użytkownika w 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
Uprawnienia do odczytu są przyznawane i zwalniane automatycznie przez platformę w przypadku wszystkich
identyfikatorów URI treści w
ładunku przekazywanym do OnReceiveContentListener.
Zwykle aplikacja przetwarza identyfikatory URI treści w usłudze lub aktywności. W przypadku
długotrwałego przetwarzania użyj
WorkManagera. Gdy to zrobisz
, rozszerz uprawnienia na docelową usługę lub aktywność, przekazując
treść za pomocą
Intent.setClipData
i ustawiając flagę
FLAG_GRANT_READ_URI_PERMISSION.
Możesz też użyć wątku w tle w bieżącym kontekście do przetwarzania treści. W takim przypadku musisz zachować odniesienie do obiektu payload otrzymanego przez odbiornik, aby mieć pewność, że platforma nie cofnie uprawnień przedwcześnie.
Widoki niestandardowe
Jeśli Twoja aplikacja używa niestandardowej podklasy View, upewnij się, że OnReceiveContentListener nie jest pomijany.
Jeśli klasa View zastępuje metodę
onCreateInputConnection
, użyj interfejsu API Jetpack
InputConnectionCompat.createWrapper
, aby skonfigurować InputConnection.
Jeśli klasa View zastępuje metodę
onTextContextMenuItem
, przekieruj do super, gdy pozycja menu to
R.id.paste lub
R.id.pasteAsPlainText.
Porównanie z interfejsem API obrazu z klawiatury
Interfejs API OnReceiveContentListener można traktować jako kolejną wersję dotychczasowego interfejsu API obrazu z klawiatury. Ten ujednolicony interfejs API obsługuje funkcje interfejsu API obrazu z klawiatury oraz kilka dodatkowych funkcji. Zgodność z urządzeniami i funkcjami zależy od tego, czy używasz biblioteki Jetpack, czy natywnych interfejsów API z pakietu Android SDK.
| Zajęcia lub funkcja | Obsługiwane przez interfejs API obrazu z klawiatury | Obsługiwane przez ujednolicony interfejs API |
|---|---|---|
| Wstawianie z klawiatury | Tak (poziom API 13 i wyższy) | Tak (poziom API 13 i wyższy) |
| Wstawianie za pomocą opcji wklejania z menu wyświetlanego po naciśnięciu i przytrzymaniu | Nie | Tak |
| Wstawianie za pomocą przeciągania i upuszczania | Nie | Tak (poziom API 24 i wyższy) |
| Zajęcia lub funkcja | Obsługiwane przez interfejs API obrazu z klawiatury | Obsługiwane przez ujednolicony interfejs API |
|---|---|---|
| Wstawianie z klawiatury | Tak (poziom API 25 i wyższy) | Tak (Android 12 i nowszy) |
| Wstawianie za pomocą opcji wklejania z menu wyświetlanego po naciśnięciu i przytrzymaniu | Nie | |
| Wstawianie za pomocą przeciągania i upuszczania | Nie |