odsyłanie użytkownika do innej aplikacji;

Jedną z najważniejszych funkcji Androida jest możliwość skierowania użytkownika do innej aplikacji w zależności od pożądanego „działania”. Jeśli np. Twoja aplikacja zawiera adres firmy, którą chcesz pokazać na mapie, nie musisz tworzyć w niej aktywności wyświetlającej mapę. Zamiast tego możesz utworzyć żądanie wyświetlenia adresu za pomocą Intent. System Android uruchamia wtedy aplikację, która może pokazywać adres na mapie.

Jak wyjaśniliśmy w pierwszej klasie, Tworzenie pierwszej aplikacji, do poruszania się między działaniami we własnej aplikacji musisz używać intencji. Zwykle robi się to za pomocą intencji jednoznacznej, która określa dokładną nazwę klasy komponentu, który chcesz uruchomić. Jeśli jednak chcesz, aby inna aplikacja wykonywała działanie, np. „wyświetl mapę”, musisz użyć intencji niejawnej.

Z tej lekcji dowiesz się, jak utworzyć pośrednią intencję dla danego działania i jak ją wykorzystać do uruchomienia działania, które wykonuje to działanie w innej aplikacji. Obejrzyj też umieszczony tutaj film, aby zrozumieć, dlaczego ważne jest uwzględnienie kontroli w czasie działania w przypadku niejawnych intencji.

Tworzenie intencji niejawnej

Intencje ogólne nie deklarują na początku nazwy klasy komponentu, ale deklarują działanie do wykonania. Czynność ta określa, co chcesz zrobić, np. wyświetl, edytuj, wyślij lub pobierz.

Powiąż działania intencji z danymi

Intencje często zawierają też dane powiązane z działaniem, np. adres, który chcesz wyświetlić, lub e-mail, który chcesz wysłać. W zależności od intencji, którą chcesz utworzyć, danymi mogą być Uri, jeden z kilku innych typów danych lub intencja może w ogóle nie potrzebować danych.

Jeśli dane to Uri, możesz użyć prostego konstruktora Intent(), którego możesz użyć do zdefiniowania działania i danych.

Jak na przykład utworzyć intencję do nawiązania połączenia telefonicznego przy użyciu danych Uri i podając numer telefonu:

Kotlin

val callIntent: Intent = Uri.parse("tel:5551234").let { number ->
    Intent(Intent.ACTION_DIAL, number)
}

Java

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

Gdy aplikacja wywoła tę intencję, dzwoniąc pod numer startActivity(), aplikacja Telefon inicjuje połączenie z podanym numerem telefonu.

Oto kilka innych intencji wraz z ich działaniami i parami danych Uri:

wyświetlać mapę,

Kotlin

// Map point based on address
val mapIntent: Intent = Uri.parse(
        "geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"
).let { location ->
    // Or map point based on latitude/longitude
    // val location: Uri = Uri.parse("geo:37.422219,-122.08364?z=14") // z param is zoom level
    Intent(Intent.ACTION_VIEW, location)
}

Java

// Map point based on address
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

Wyświetl stronę internetową

Kotlin

val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage ->
    Intent(Intent.ACTION_VIEW, webpage)
}

Java

Uri webpage = Uri.parse("https://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

Dodaj dodatki do intencji

Inne rodzaje intencji niejawnych wymagają „dodatkowych” danych z różnymi typami danych, np. ciągiem znaków. Możesz dodać jeden lub więcej dodatkowych danych, korzystając z różnych metod putExtra().

Domyślnie system określa odpowiedni typ MIME wymagany przez intencję na podstawie uwzględnionych danych Uri. Jeśli nie podasz elementu Uri w zamiarze, zazwyczaj do określenia typu danych powiązanych z intencją należy użyć atrybutu setType(). Ustawienie typu MIME dokładniej określa, które rodzaje aktywności mają otrzymywać intencję.

Oto kilka intencji, które dodają więcej danych do sprecyzowania oczekiwanego działania:

Wysyłanie e-maila z załącznikiem

Kotlin

Intent(Intent.ACTION_SEND).apply {
    // The intent does not have a URI, so declare the "text/plain" MIME type
    type = "text/plain"
    putExtra(Intent.EXTRA_EMAIL, arrayOf("jan@example.com")) // recipients
    putExtra(Intent.EXTRA_SUBJECT, "Email subject")
    putExtra(Intent.EXTRA_TEXT, "Email message text")
    putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"))
    // You can also attach multiple items by passing an ArrayList of Uris
}

Java

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jan@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris

Tworzenie wydarzenia w kalendarzu

Uwaga: ta intencja dotycząca wydarzenia w kalendarzu jest obsługiwana tylko w interfejsie API na poziomie 14 lub wyższym.

Kotlin

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply {
    val beginTime: Calendar = Calendar.getInstance().apply {
        set(2021, 0, 23, 7, 30)
    }
    val endTime = Calendar.getInstance().apply {
        set(2021, 0, 23, 10, 30)
    }
    putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.timeInMillis)
    putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.timeInMillis)
    putExtra(Events.TITLE, "Ninja class")
    putExtra(Events.EVENT_LOCATION, "Secret dojo")
}

Java

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance();
beginTime.set(2021, 0, 23, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2021, 0, 23, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

Uwaga: ważne jest, aby wartość Intent była jak najbardziej dokładna. Jeśli na przykład chcesz wyświetlić obraz z użyciem intencji ACTION_VIEW, podaj typ MIME image/*. Zapobiega to wywoływaniu przez intencję aplikacji, które mogą wyświetlać inne typy danych (np. aplikacje do map).

Rozpoczynanie działania z zamiarem

Po utworzeniu Intent i skonfigurowaniu dodatkowych informacji zadzwoń pod numer startActivity(), aby wysłać je do systemu:

Kotlin

startActivity(intent)

Java

startActivity(intent);

Radzenie sobie z sytuacją, w której żadna aplikacja nie może otrzymać intencji

Wiele intencji obsługuje inną aplikację zainstalowaną na urządzeniu (np. aplikację na telefon, pocztę e-mail czy kalendarz), ale Twoja aplikacja powinna przygotować się na sytuację, w której żadna aktywność nie jest w stanie obsłużyć intencji aplikacji. Gdy wywołujesz intencję, przygotuj się na przechwycenie ActivityNotFoundException, co następuje, gdy nie ma innego działania, które mogłoby obsłużyć intencję aplikacji:

Kotlin

try {
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

try {
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Gdy zauważysz ten wyjątek, zdecyduj, co ma robić aplikacja. Następny krok zależy od specyficznych cech intencji, który chcesz wywołać. Jeśli na przykład znasz aplikację, która może obsłużyć intencję, podaj użytkownikowi link umożliwiający jej pobranie. Dowiedz się więcej o tworzeniu linku do produktu w Google Play.

Okno wyboru

Jeśli system wykryje więcej niż 1 aktywność, która może obsłużyć intencję, wyświetli okno (nazywane czasami „oknem różnicowania”), aby użytkownik mógł wybrać aplikację, której chce użyć (jak pokazano na rysunku 1). Jeśli istnieje tylko jedna czynność, która obsługuje intencję, system natychmiast ją uruchamia.

U dołu ekranu pojawi się panel. W tym panelu wymienione są różne aplikacje, które mogą obsłużyć intencję.

Rysunek 1. Przykład okna wyboru, które pojawia się, gdy więcej niż 1 aplikacja może obsłużyć intencję.

Pełny przykład

Oto pełny przykład, który pokazuje, jak utworzyć intencję wyświetlenia mapy, sprawdzić, czy aplikacja istnieje do obsługi intencji, a następnie ją uruchomić:

Kotlin

// Build the intent.
val location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California")
val mapIntent = Intent(Intent.ACTION_VIEW, location)

// Try to invoke the intent.
try {
    startActivity(mapIntent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

// Build the intent.
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// Try to invoke the intent.
try {
    startActivity(mapIntent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Pokaż wybór aplikacji

Rysunek 2. Okno wyboru.

Zwróć uwagę, że gdy rozpoczynasz działanie, przekazując Intent do startActivity(), a więcej niż jedna aplikacja odpowiada na intencję, użytkownik może wybrać aplikację domyślną (zaznaczając pole wyboru u dołu okna; patrz rys. 1). Jest to przydatne w przypadku czynności, do których użytkownicy zwykle chcą za każdym razem używać tej samej aplikacji, np. otwierania strony internetowej (użytkownicy prawdopodobnie używają tylko jednej przeglądarki) lub robienia zdjęcia (użytkownicy preferują jeden aparat).

Jeśli jednak działanie może być wykonywane przez wiele aplikacji, a użytkownik za każdym razem może preferować inną aplikację – może to być np. działanie udostępniania, w przypadku którego użytkownicy mogą udostępniać jeden element. Musisz wyraźnie pokazać okno wyboru, jak widać na ilustracji 2. Okno wyboru wymusza każdorazowe wybranie aplikacji, której chcesz użyć do wykonania danego działania (nie może on wybrać domyślnej aplikacji dla tego działania).

Aby pokazać selektor, utwórz dokument Intent za pomocą createChooser() i przekaż go do startActivity(). Na przykład:

Kotlin

val intent = Intent(Intent.ACTION_SEND)

// Create intent to show chooser
val chooser = Intent.createChooser(intent, /* title */ null)

// Try to invoke the intent.
try {
    startActivity(chooser)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);

// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, /* title */ null);

// Try to invoke the intent.
try {
    startActivity(chooser);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Pojawi się okno z listą aplikacji, które odpowiadają na intencję przekazaną do metody createChooser(). Parametr title może być podany, jeśli działanie nie jest wartością ACTION_SEND ani ACTION_SEND_MULTIPLE