Odbieranie danych z innych aplikacji

Aplikacja może nie tylko wysyłać dane do innych aplikacji, ale też je od nich odbierać. Zastanów się, jak użytkownicy korzystają z Twojej aplikacji i jakie typy danych chcesz otrzymywać z innych aplikacji. Na przykład aplikacja sieci społecznościowej może być zainteresowana otrzymywaniem treści tekstowych, takich jak interesujący adres URL, z innej aplikacji.

W aplikacji korzystającej z Nawigacji w Compose odbieranie danych wysłanych przez inną aplikację jest procesem 3-etapowym:

  1. Zadeklaruj <intent-filter> w pliku manifestu: musisz dodać filtr intencji do aktywności w pliku AndroidManifest.xml. Informuje to system operacyjny Android, że aplikacja może odbierać określone działania (takie jak ACTION_SEND) i typy MIME (takie jak text/plain).

  2. Zdefiniuj navDeepLink na wykresie nawigacji w Compose: dołącz navDeepLink, który pasuje do działania i typu MIME, bezpośrednio do elementu kompozycyjnego, który powinien wyświetlać treść. NavController automatycznie przechwytuje przychodzącą intencję i kieruje użytkownika bezpośrednio na ten ekran.

  3. Wyodrębnij przychodzące dane: na ekranie docelowym uzyskaj dostęp do dodatkowych danych intencji (takich jak EXTRA_TEXT lub EXTRA_STREAM), aby pobrać udostępnione treści i zaktualizować stan interfejsu.

Cele udostępniania bezpośredniego to precyzyjne linki do konkretnej aktywności w aplikacji. Często reprezentują one osobę lub grupę i są wyświetlane w arkuszu udostępniania w Androidzie. Na przykład aplikacja do obsługi wiadomości może udostępniać cel bezpośredniego udostępniania dla osoby, która zawiera precyzyjny link bezpośrednio do rozmowy z tą osobą. Szczegółowe instrukcje znajdziesz w artykule Udostępnianie celów udostępniania bezpośredniego.

Obsługiwane typy MIME

Najlepiej, aby aplikacja mogła odbierać jak najszerszy zakres typów MIME. Na przykład aplikacja do obsługi wiadomości przeznaczona do wysyłania tekstu, obrazów i filmów powinna obsługiwać odbieranie obiektów text/*, image/* i video/*. Oto kilka typowych typów MIME do wysyłania i odbierania danych na Androidzie.

Odbiorcy rejestrują się w usłudze Nadawcy wysyłają
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
image/*
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
Obsługiwane rozszerzenia plików application/pdf

Zobacz oficjalny rejestr typów MIME IANA.

Tworzenie świetnych odbiorców udostępniania

Gdy użytkownicy klikną cel udostępniania powiązany z konkretną aktywnością, pozwól im potwierdzić i edytować udostępniane treści, zanim aplikacja ich użyje. Jest to szczególnie ważne w przypadku danych tekstowych.

Odbieranie danych w aplikacji

Odbieranie udostępnionych danych w aplikacji korzystającej z Compose wymaga zadeklarowania filtrów intencji w pliku manifestu, przekierowania przychodzących intencji do odpowiedniego ekranu za pomocą precyzyjnych linków i wyodrębnienia ładunku z intencji w celu zaktualizowania interfejsu.

Aktualizowanie pliku manifestu

Filtry intencji informują system, które intencje akceptuje komponent aplikacji. Podobnie jak w przypadku tworzenia intencji z działaniem ACTION_SEND w lekcji Wysyłanie danych do innych aplikacji, tworzysz filtry intencji, aby otrzymywać intencje z tym działaniem. Filtr intencji definiuje się w pliku manifestu za pomocą elementu <intent-filter>. Jeśli na przykład aplikacja obsługuje odbieranie treści tekstowych, plik manifestu zawierający co najmniej 1 obraz dowolnego typu będzie wyglądał jak ten fragment kodu:

<activity android:name=".ui.MyActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

Gdy inna aplikacja próbuje udostępnić którykolwiek z tych elementów, tworząc intencję i przekazując ją do startActivity(), Twoja aplikacja jest wymieniona jako opcja w arkuszu udostępniania w Androidzie lub w rozpoznawaniu intencji. Jeśli użytkownik wybierze Twoją aplikację, uruchomi się odpowiednia aktywność (.ui.MyActivity w poprzednim przykładzie). Następnie musisz odpowiednio obsłużyć te treści w kodzie i interfejsie.

W Compose Navigation dołącz navDeepLink bezpośrednio do miejsca docelowego funkcji kompozycyjnej, które ma wyświetlać treść. Gdy inna aplikacja udostępnia dane, które pasują do filtra intencji, Compose Navigation kieruje użytkownika bezpośrednio do tego miejsca docelowego:

navDeepLink dopasowuje działanie i typ MIME przychodzącej intencji, aby przejść do odpowiedniego ekranu docelowego. Po dotarciu do miejsca docelowego moduł obsługi sprawdza intencję, aby określić, jaki ładunek został odebrany (np. pojedynczy obraz lub wiele obrazów), i wyodrębnia odpowiednie dodatki.

Zarządzanie treściami przychodzącymi

Aby pobrać treści dostarczone przez Intent, odczytaj bieżącą aktywność z LocalActivity.current w funkcji kompozycyjnej, a następnie sprawdź intencję, aby określić, co zrobić dalej. Jeśli tę aktywność można rozpocząć z innych części systemu (np. z programu uruchamiającego), weź to pod uwagę podczas sprawdzania intencji.

Zwróć szczególną uwagę na przychodzące dane: może być ustawiony nieprawidłowy typ MIME lub wysyłany obraz może być bardzo duży. Przetwarzaj dane binarne lub wykonuj operacje wejścia/wyjścia (takie jak dekodowanie dużych obrazów lub zapisywanie plików) asynchronicznie, używając współprogramów (takich jak Dispatchers.IO), a nie w głównym wątku UI.

@Composable
fun SharesheetHandler() {
    val activity = LocalActivity.current
    val intent = activity?.intent

    when (intent?.action) {
        Intent.ACTION_SEND -> {
            if (intent.type == "text/plain") {
                handleSendText(intent) // Handle text being sent
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (intent.type?.startsWith("image/") == true) {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }

        else -> {
            // Handle other intents, such as being started from the home screen
        }
    }
}

private fun handleSendText(intent: Intent) {
    intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
        // Update UI state with the shared text
    }
}

private fun handleSendImage(intent: Intent) {
    val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUri?.let {
        // Update UI state with the shared image
    }
}

private fun handleSendMultipleImages(intent: Intent) {
    val imageUris =
        IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUris?.let {
        // Update UI state with the shared images
    }
}

Podczas wyodrębniania danych binarnych lub identyfikatorów URI z dodatków intencji (takich jak EXTRA_STREAM) używaj funkcji IntentCompat.getParcelableExtra() lub IntentCompat.getParcelableArrayListExtra() z biblioteki AndroidX Core, jak pokazano w funkcjach handleSendImage i handleSendMultipleImages powyżej. W Androidzie 13 (poziom API 33) wycofano metodę Intent.getParcelableExtra(String) bez parametrów na rzecz metod bezpiecznych pod względem typu, które przyjmują oczekiwany typ klasy.

Aktualizacja interfejsu po otrzymaniu danych może być tak prosta jak aktualizacja stanu w celu wypełnienia TextField lub tak złożona jak zastosowanie filtra do obrazu. To, co stanie się dalej, zależy od aplikacji.

Udostępnianie adresu URL zrzutu ekranu

Podczas robienia zrzutu ekranu możesz udostępnić zrzut ekranu i powiązany z nim adres URL. Zapewnia to użytkownikom lepsze wrażenia. Podczas odbierania adresu URL pamiętaj, aby pobrać pole EXTRA_TEXT z intencji, jak w tym przykładzie:

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update UI state with the shared image and the EXTRA_TEXT if available
}

Upewnij się, że użytkownicy rozpoznają Twoją aplikację

Aplikacja jest reprezentowana przez ikonę i etykietę w arkuszu udostępniania w Androidzie i w rozpoznawaniu intencji. Oba te elementy są zdefiniowane w pliku manifestu. Możesz ustawić etykiety filtrów Activity lub filtrów intencji, aby podać więcej kontekstu.

Od Androida 10 (poziom interfejsu API 29) arkusz udostępniania w Androidzie używa tylko ikon ustawionych w pliku manifestu w tagu application. Android ignoruje ikony ustawione w tagach intent-filter i activity.

Otrzymywanie szczegółowych treści

Intencje ACTION_SEND umożliwiają odbieranie danych z arkusza udostępniania w Androidzie i rozpoznawania intencji na poziomie aktywności lub nawigacji, ale aplikacje mogą też odbierać szczegółowe treści (takie jak obrazy, filmy, pliki audio i tekst sformatowany) przez bezpośrednie interakcje z interfejsem. Te mechanizmy obejmują:

  • wklejanie ze schowka (menu po naciśnięciu i przytrzymaniu),
  • wstawianie multimediów bezpośrednio z klawiatury ekranowej (IME), np. naklejek lub GIF-ów;
  • przeciąganie i upuszczanie treści z innej aplikacji w trybie wielu okien lub podzielonego ekranu;

W interfejsach opartych na widoku Android 12 (poziom API 31) i AndroidX Core 1.7 wprowadzają ujednolicony interfejs API OnReceiveContentListener. Ten detektor konsoliduje obsługę treści ze schowka, klawiatury i przeciągania i upuszczania w jednym wywołaniu zwrotnym. Szczegółowe instrukcje dotyczące implementacji tej funkcji w widokach znajdziesz w artykule Odbieranie szczegółowych treści.

W Jetpack Compose możesz obsługiwać odbieranie szczegółowych treści wstawianych do komponentów interfejsu (takich jak pola tekstowe) za pomocą modyfikatora Modifier.contentReceiver lub modyfikatorów przeciągania i upuszczania.