Intent
to obiekt wiadomości, którego możesz użyć, aby poprosić o wykonanie działania przez inny komponent aplikacji.
Intencje ułatwiają komunikację między komponentami na kilka sposobów, ale istnieją 3 podstawowe przypadki użycia:
- Rozpoczynanie aktywności
Symbol
Activity
reprezentuje pojedynczy ekran w aplikacji. Nową instancję elementuActivity
możesz utworzyć, przekazując elementIntent
do elementustartActivity()
.Intent
opisuje aktywność, którą należy rozpocząć, i zawiera niezbędne dane.Jeśli chcesz otrzymać wynik działania po jego zakończeniu, wywołaj funkcję
startActivityForResult()
. Twoja aktywność otrzymuje wynik jako osobny obiektIntent
w wywołaniu zwrotnymonActivityResult()
. Więcej informacji znajdziesz w przewodniku Działania. - Uruchamianie usługi
Service
to komponent, który wykonuje operacje w tle bez interfejsu użytkownika. W Androidzie 5.0 (poziom interfejsu API 21) i nowszych wersjach możesz uruchomić usługę za pomocąJobScheduler
. Więcej informacji oJobScheduler
znajdziesz wAPI-reference documentation
.W przypadku wersji starszych niż Android 5.0 (poziom interfejsu API 21) możesz uruchomić usługę, korzystając z metod klasy
Service
. Możesz uruchomić usługę, aby wykonać jednorazową operację (np. pobrać plik), przekazującIntent
dostartService()
.Intent
opisuje usługę, którą należy uruchomić, i zawiera niezbędne dane.Jeśli usługa jest zaprojektowana z interfejsem klient-serwer, możesz powiązać ją z innym komponentem, przekazując
Intent
dobindService()
. Więcej informacji znajdziesz w przewodniku po usługach. - Nadawanie transmisji
Broadcast to wiadomość, którą może odebrać dowolna aplikacja. System dostarcza różne transmisje dotyczące zdarzeń systemowych, np. uruchomienia systemu lub rozpoczęcia ładowania urządzenia. Możesz dostarczyć transmisję do innych aplikacji, przekazując
Intent
dosendBroadcast()
lubsendOrderedBroadcast()
.
W dalszej części tej strony wyjaśniamy, jak działają intencje i jak z nich korzystać. Więcej informacji znajdziesz w sekcjach Interakcje z innymi aplikacjami i Udostępnianie treści.
Rodzaje intencji
Istnieją 2 rodzaje intencji:
- Jawne intencje określają, który komponent której aplikacji zrealizuje intencję, poprzez podanie pełnego
ComponentName
. Zwykle używasz intencji jawnej, aby uruchomić komponent w swojej aplikacji, ponieważ znasz nazwę klasy aktywności lub usługi, którą chcesz uruchomić. Możesz na przykład rozpocząć nową aktywność w aplikacji w odpowiedzi na działanie użytkownika lub uruchomić usługę, aby pobrać plik w tle. - Intencje ogólne nie określają konkretnego komponentu, ale deklarują ogólne działanie, które ma zostać wykonane, co umożliwia obsługę intencji przez komponent z innej aplikacji. Jeśli na przykład chcesz pokazać użytkownikowi lokalizację na mapie, możesz użyć niejawnego zamiaru, aby poprosić inną aplikację o wyświetlenie określonej lokalizacji na mapie.
Ilustracja 1 pokazuje, jak intencja jest używana podczas rozpoczynania aktywności. Gdy Intent
zawiera nazwę konkretnego komponentu aktywności, system natychmiast go uruchamia.

Rysunek 1. Sposób, w jaki niejawny zamiar jest przekazywany przez system, aby rozpocząć inną aktywność: [1] Aktywność A tworzy Intent
z opisem działania i przekazuje go do startActivity()
. [2] System Android wyszukuje we wszystkich aplikacjach filtr intencji, który pasuje do intencji. Gdy znajdziemy odpowiednik, [3] system rozpoczyna działanie dopasowywania (działanie B), wywołując jego metodę onCreate()
i przekazując jej wartość Intent
.
Gdy używasz intencji niejawnej, system Android znajduje odpowiedni komponent do uruchomienia, porównując zawartość intencji z filtrami intencji zadeklarowanymi w pliku manifestu innych aplikacji na urządzeniu. Jeśli intencja pasuje do filtra intencji, system uruchamia ten komponent i przekazuje mu obiekt Intent
. Jeśli zgodnych jest kilka filtrów intencji, system wyświetla okno dialogowe, w którym użytkownik może wybrać aplikację, której chce użyć.
Filtr intencji to wyrażenie w pliku manifestu aplikacji, które określa typy intencji, jakie komponent chce otrzymywać. Na przykład deklarując filtr intencji dla aktywności, umożliwiasz innym aplikacjom bezpośrednie uruchamianie tej aktywności za pomocą określonego rodzaju intencji. Podobnie jeśli nie zadeklarujesz żadnych filtrów intencji dla aktywności, można ją uruchomić tylko za pomocą jawnej intencji.
Ostrzeżenie: aby zapewnić bezpieczeństwo aplikacji, zawsze używaj jawnego zamiaru podczas uruchamiania Service
i nie deklaruj filtrów intencji dla usług. Używanie niejawnego zamiaru do uruchamiania usługi jest niebezpieczne, ponieważ nie można mieć pewności, która usługa odpowie na zamiar, a użytkownik nie widzi, która usługa się uruchamia. Począwszy od Androida 5.0 (interfejs API na poziomie 21), system zgłasza wyjątek, jeśli wywołasz bindService()
za pomocą niejawnego zamiaru.
Tworzenie intencji
Obiekt Intent
zawiera informacje, których system Android używa do określania, który komponent ma zostać uruchomiony (np. dokładna nazwa komponentu lub kategoria komponentu, który powinien otrzymać intencję), oraz informacje, których komponent odbiorcy używa do prawidłowego wykonania działania (np. działanie do wykonania i dane, na których ma zostać wykonane).
Główne informacje zawarte w Intent
to:
- Nazwa komponentu
- Nazwa komponentu, który ma zostać uruchomiony.
Jest to opcjonalne, ale jest to kluczowa informacja, która sprawia, że intencja jest jawna, co oznacza, że powinna być dostarczana tylko do komponentu aplikacji zdefiniowanego przez nazwę komponentu. Jeśli nazwa komponentu nie jest podana, intencja jest niejawna, a system decyduje, który komponent powinien ją otrzymać, na podstawie innych informacji o intencji (takich jak działanie, dane i kategoria – opisanych poniżej). Jeśli chcesz uruchomić konkretny komponent w aplikacji, podaj jego nazwę.
Uwaga: podczas uruchamiania
Service
zawsze podawaj nazwę komponentu. W przeciwnym razie nie będziesz mieć pewności, która usługa odpowie na intencję, a użytkownik nie będzie widzieć, która usługa się uruchamia.To pole
Intent
jest obiektemComponentName
, który możesz określić za pomocą pełnej nazwy klasy komponentu docelowego, w tym nazwy pakietu aplikacji, np.com.example.ExampleActivity
. Nazwę komponentu możesz ustawić za pomocą atrybutówsetComponent()
,setClass()
,setClassName()
lub konstruktoraIntent
. - Czynność
- Ciąg znaków określający ogólne działanie do wykonania (np. view lub pick).
W przypadku intencji transmisji jest to działanie, które zostało wykonane i jest zgłaszane. Działanie w dużej mierze określa strukturę pozostałej części intencji, zwłaszcza informacje zawarte w danych i dodatkach.
Możesz określić własne działania, które będą używane przez intencje w aplikacji (lub przez inne aplikacje do wywoływania komponentów w Twojej aplikacji), ale zwykle określasz stałe działania zdefiniowane przez klasę
Intent
lub inne klasy platformy. Oto kilka typowych działań, które możesz wykonać, aby rozpocząć aktywność:ACTION_VIEW
- Użyj tego działania w intencji z
startActivity()
, gdy masz informacje, które aktywność może wyświetlić użytkownikowi, np. zdjęcie do wyświetlenia w aplikacji galerii lub adres do wyświetlenia w aplikacji map. ACTION_SEND
- Znany też jako intencja share. Używaj go w intencji z
startActivity()
, gdy masz dane, które użytkownik może udostępnić za pomocą innej aplikacji, np. aplikacji do obsługi poczty e-mail lub aplikacji do udostępniania w mediach społecznościowych.
Więcej stałych definiujących ogólne działania znajdziesz w
Intent
dokumentacji klasy. Inne działania są zdefiniowane w innych miejscach platformy Android, np. wSettings
w przypadku działań, które otwierają określone ekrany w aplikacji Ustawienia systemu.Działanie dla intencji możesz określić za pomocą
setAction()
lub konstruktoraIntent
.Jeśli definiujesz własne działania, pamiętaj, aby dodać nazwę pakietu aplikacji jako prefiks, jak pokazano w tym przykładzie:
Kotlin
const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"
Java
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
- Dane
- Identyfikator URI (obiekt
Uri
), który odwołuje się do danych, na których mają być wykonywane działania, lub typ MIME tych danych. Rodzaj dostarczanych danych jest zwykle określany przez działanie intencji. Jeśli na przykład działanie toACTION_EDIT
, dane powinny zawierać adres URI dokumentu do edycji.Podczas tworzenia intencji często ważne jest, aby oprócz identyfikatora URI określić typ danych (jego typ MIME). Na przykład aktywność, która może wyświetlać obrazy, prawdopodobnie nie będzie w stanie odtworzyć pliku audio, mimo że formaty URI mogą być podobne. Określenie typu MIME danych pomaga systemowi Android znaleźć najlepszy komponent do odebrania intencji. Typ MIME można jednak czasami wywnioskować z identyfikatora URI, zwłaszcza gdy dane są identyfikatorem URI
content:
. Identyfikatorcontent:
URI wskazuje, że dane znajdują się na urządzeniu i są kontrolowane przezContentProvider
, co sprawia, że typ MIME danych jest widoczny dla systemu.Aby ustawić tylko identyfikator URI danych, wywołaj funkcję
setData()
. Aby ustawić tylko typ MIME, wywołaj funkcjęsetType()
. W razie potrzeby możesz ustawić oba parametry za pomocą znakusetDataAndType()
.Uwaga: jeśli chcesz ustawić zarówno URI, jak i typ MIME, nie wywołuj funkcji
setData()
isetType()
, ponieważ każda z nich unieważnia wartość drugiej. Zawsze używaj znakusetDataAndType()
, aby ustawić zarówno URI, jak i typ MIME. - Kategoria
- Ciąg znaków zawierający dodatkowe informacje o rodzaju komponentu, który powinien obsługiwać intencję. W intencji można umieścić dowolną liczbę opisów kategorii, ale większość intencji nie wymaga kategorii.
Oto kilka typowych kategorii:
CATEGORY_BROWSABLE
- Aktywność docelowa może być uruchamiana przez przeglądarkę internetową w celu wyświetlania danych, do których odwołuje się link, np. obrazu lub wiadomości e-mail.
CATEGORY_LAUNCHER
- Aktywność jest początkową aktywnością zadania i jest wymieniona w menu aplikacji systemu.
Pełną listę kategorii znajdziesz w
Intent
opisie klasy.Kategorię możesz określić za pomocą tagu
addCategory()
.
Wymienione powyżej właściwości (nazwa komponentu, działanie, dane i kategoria) reprezentują cechy definiujące intencję. Odczytując te właściwości, system Android może określić, który komponent aplikacji powinien uruchomić. Intencja może jednak zawierać dodatkowe informacje, które nie wpływają na sposób jej przekształcenia w komponent aplikacji. Intencja może też zawierać te informacje:
- Dodatki
- Pary klucz-wartość zawierające dodatkowe informacje wymagane do wykonania żądanego działania.
Podobnie jak niektóre działania używają określonych rodzajów identyfikatorów URI danych, niektóre działania używają też określonych dodatków.
Możesz dodawać dodatkowe dane za pomocą różnych
putExtra()
metod, z których każda przyjmuje 2 parametry: nazwę klucza i wartość. Możesz też utworzyć obiektBundle
ze wszystkimi dodatkowymi danymi, a następnie wstawić obiektBundle
do obiektuIntent
za pomocą metodyputExtras()
.Na przykład podczas tworzenia intencji wysłania e-maila z
ACTION_SEND
możesz określić odbiorcę to za pomocą kluczaEXTRA_EMAIL
i określić subject za pomocą kluczaEXTRA_SUBJECT
.Klasa
Intent
określa wiele stałychEXTRA_*
dla standardowych typów danych. Jeśli musisz zadeklarować własne dodatkowe klucze (dla intencji, które odbiera Twoja aplikacja), pamiętaj, aby dodać nazwę pakietu aplikacji jako prefiks, jak pokazano w tym przykładzie:Kotlin
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Java
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Ostrzeżenie: nie używaj danych
Parcelable
aniSerializable
podczas wysyłania intencji, która ma być odebrana przez inną aplikację. Jeśli aplikacja próbuje uzyskać dostęp do danych w obiekcieBundle
, ale nie ma dostępu do klasy przekazanej lub serializowanej, system zgłasza wyjątekRuntimeException
. - Flagi
- Flagi są zdefiniowane w klasie
Intent
i pełnią funkcję metadanych intencji. Flagi mogą instruować system Android, jak uruchomić aktywność (np. do którego zadania ma należeć aktywność) i jak ją traktować po uruchomieniu (np. czy ma należeć do listy ostatnich aktywności).Więcej informacji znajdziesz w opisie metody
setFlags()
.
Przykładowa intencja bezpośrednia
Intencja jawna służy do uruchamiania konkretnego komponentu aplikacji, np. określonej aktywności lub usługi w aplikacji. Aby utworzyć intencję jawną, zdefiniuj nazwę komponentu dla obiektu Intent
– wszystkie inne właściwości intencji są opcjonalne.
Jeśli na przykład w aplikacji masz usługę o nazwie DownloadService
, która pobiera plik z internetu, możesz ją uruchomić za pomocą tego kodu:
Kotlin
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
Java
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" Intent downloadIntent = new Intent(this, DownloadService.class); downloadIntent.setData(Uri.parse
(fileUrl)); startService(downloadIntent);
Konstruktor Intent(Context, Class)
dostarcza aplikacji Context
, a komponentowi obiekt Class
. W związku z tym ten zamiar wyraźnie uruchamia w aplikacji klasę DownloadService
.
Więcej informacji o tworzeniu i uruchamianiu usługi znajdziesz w przewodniku Usługi.
Przykładowa intencja ogólna
Intencja ogólna określa działanie, które może wywołać dowolną aplikację na urządzeniu, która jest w stanie je wykonać. Używanie niejawnego zamiaru jest przydatne, gdy Twoja aplikacja nie może wykonać działania, ale inne aplikacje prawdopodobnie mogą to zrobić i chcesz, aby użytkownik wybrał, której aplikacji użyć.
Jeśli na przykład masz treści, które użytkownik ma udostępnić innym osobom, utwórz intencję z działaniem ACTION_SEND
i dodaj dodatkowe informacje określające treści do udostępnienia. Gdy wywołasz
startActivity()
z tą intencją, użytkownik będzie mógł
wybrać aplikację, za pomocą której udostępni treści.
Kotlin
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
// Create the text message with a string. Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); sendIntent.setType("text/plain"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Gdy wywoływana jest funkcja startActivity()
, system sprawdza wszystkie zainstalowane aplikacje, aby określić, które z nich mogą obsłużyć ten rodzaj intencji (intencję z działaniem ACTION_SEND
i danymi „text/plain”). Jeśli jest tylko jedna aplikacja, która może obsłużyć intencję, zostanie ona natychmiast otwarta i otrzyma intencję. Jeśli żadna inna aplikacja nie może tego zrobić, Twoja aplikacja może przechwycić występujący
ActivityNotFoundException
. Jeśli intencję akceptuje kilka działań, system wyświetla okno dialogowe, takie jak na rysunku 2, aby użytkownik mógł wybrać aplikację, której chce użyć.
Więcej informacji o uruchamianiu innych aplikacji znajdziesz też w przewodniku na temat przekierowywania użytkownika do innej aplikacji.

Rysunek 2. Okno wyboru.
Wymuszanie wyboru aplikacji
Jeśli na Twoją intencję niejawną odpowiada więcej niż jedna aplikacja, użytkownik może wybrać, której z nich chce użyć, i ustawić ją jako domyślną dla danego działania. Możliwość wyboru domyślnej aplikacji jest przydatna podczas wykonywania czynności, do których użytkownik prawdopodobnie chce za każdym razem używać tej samej aplikacji, np. podczas otwierania strony internetowej (użytkownicy często wolą tylko jedną przeglądarkę).
Jeśli jednak na intencję może odpowiedzieć kilka aplikacji, a użytkownik może chcieć za każdym razem używać innej aplikacji, musisz wyraźnie wyświetlić okno wyboru. W oknie wyboru wyświetla się prośba o wybranie aplikacji, która ma wykonać działanie (użytkownik nie może wybrać aplikacji domyślnej dla tego działania). Jeśli na przykład Twoja aplikacja wykonuje działanie „udostępnij” za pomocą działania ACTION_SEND
, użytkownicy mogą chcieć udostępnić treści za pomocą innej aplikacji w zależności od bieżącej sytuacji, więc zawsze używaj okna wyboru, jak pokazano na rysunku 2.
Aby wyświetlić selektor, utwórz obiekt Intent
za pomocą metody createChooser()
i przekaż go do metody startActivity()
, jak pokazano w tym przykładzie.
Ten przykład wyświetla okno dialogowe z listą aplikacji, które reagują na intencję przekazaną do metody createChooser()
, i używa podanego tekstu jako tytułu okna dialogowego.
Kotlin
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Java
Intent sendIntent = new Intent(Intent.ACTION_SEND); ... // Always use string resources for UI text. // This says something like "Share this photo with" String title = getResources().getString(R.string.chooser_title); // Create intent to show the chooser dialog Intent chooser = Intent.createChooser(sendIntent, title); // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
Wykrywanie niebezpiecznych uruchomień intencji
Aplikacja może uruchamiać intencje, aby przechodzić między komponentami w jej obrębie lub wykonywać działania w imieniu innej aplikacji. Aby zwiększyć bezpieczeństwo platformy, Android 12 (poziom API 31) i nowsze wersje udostępniają funkcję debugowania, która ostrzega, gdy aplikacja uruchamia intencję w niebezpieczny sposób. Na przykład aplikacja może niebezpiecznie uruchamiać zagnieżdżoną intencję, czyli intencję przekazywaną jako dodatkowa w innej intencji.
Jeśli Twoja aplikacja wykonuje obie te czynności, system wykrywa niebezpieczne uruchomienie intencji i dochodzi do naruszenia StrictMode:
- Aplikacja rozpakowuje zagnieżdżoną intencję z dodatków dostarczonej intencji.
- Aplikacja natychmiast uruchamia komponent za pomocą tej zagnieżdżonej intencji, np. przekazując ją do funkcji
startActivity()
,startService()
lubbindService()
.
Więcej informacji o tym, jak rozpoznać tę sytuację i wprowadzić zmiany w aplikacji, znajdziesz w poście na blogu Android Nesting Intents w serwisie Medium.
Sprawdzanie niebezpiecznych uruchomień intencji
Aby sprawdzić, czy w aplikacji nie dochodzi do niebezpiecznych uruchomień intencji, podczas konfigurowania VmPolicy
wywołaj
detectUnsafeIntentLaunch()
w sposób pokazany w poniższym fragmencie kodu. Jeśli aplikacja wykryje naruszenie trybu StrictMode, możesz zatrzymać jej działanie, aby chronić potencjalnie wrażliwe informacje.
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
Java
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
Odpowiedzialne korzystanie z intencji
Aby zminimalizować ryzyko uruchomienia niebezpiecznego zamiaru i naruszenia trybu StrictMode, postępuj zgodnie z tymi sprawdzonymi metodami.
Kopiuj tylko najważniejsze dodatki w ramach intencji i przeprowadzaj niezbędne czyszczenie i weryfikację. Aplikacja może kopiować dodatki z jednej intencji do innej intencji, która jest używana do uruchamiania nowego komponentu. Dzieje się tak, gdy aplikacja wywołuje funkcje putExtras(Intent)
lub putExtras(Bundle)
.
Jeśli Twoja aplikacja wykonuje jedną z tych operacji, kopiuj tylko dodatki, których oczekuje komponent odbierający. Jeśli inny zamiar (który otrzymuje kopię) uruchamia komponent, który nie jest eksportowany, oczyść i sprawdź dodatki przed skopiowaniem ich do zamiaru, który uruchamia komponent.
Nie eksportuj niepotrzebnie komponentów aplikacji. Jeśli na przykład zamierzasz uruchomić komponent aplikacji za pomocą wewnętrznej zagnieżdżonej intencji, ustaw atrybut android:exported
tego komponentu na false
.
Zamiast zagnieżdżonego zamiaru używaj PendingIntent
. Dzięki temu, gdy inna aplikacja rozpakuje PendingIntent
z Intent
, w którym się znajduje, będzie mogła uruchomić PendingIntent
, używając tożsamości Twojej aplikacji. Ta konfiguracja umożliwia innej aplikacji bezpieczne uruchomienie dowolnego komponentu, w tym komponentu nieeksportowanego, w Twojej aplikacji.
Diagram na rysunku 2 pokazuje, jak system przekazuje kontrolę z aplikacji (klienta) do innej aplikacji (usługi) i z powrotem:
- Aplikacja tworzy intencję, która wywołuje aktywność w innej aplikacji. W tej intencji dodajesz obiekt
PendingIntent
jako dodatkowy. Ta intencja oczekująca wywołuje komponent w aplikacji, który nie jest eksportowany. - Po otrzymaniu intencji aplikacji druga aplikacja wyodrębnia zagnieżdżony obiekt
PendingIntent
. - Inna aplikacja wywołuje metodę
send()
na obiekciePendingIntent
. - Po przekazaniu kontroli z powrotem do aplikacji system wywołuje oczekujący zamiar, używając kontekstu aplikacji.
Rysunek 2. Diagram komunikacji między aplikacjami podczas korzystania z zagnieżdżonego oczekującego zamiaru.
Otrzymywanie intencji ogólnej
Aby reklamować, jakie niejawne intencje może odbierać Twoja aplikacja, zadeklaruj co najmniej 1 filtr intencji dla każdego komponentu aplikacji z elementem <intent-filter>
w pliku manifestu.
Każdy filtr intencji określa typy intencji, które akceptuje, na podstawie działania, danych i kategorii intencji. System dostarcza do komponentu aplikacji niejawną intencję tylko wtedy, gdy może ona przejść przez jeden z filtrów intencji.
Uwaga: zamiar jawny jest zawsze dostarczany do miejsca docelowego, niezależnie od filtrów zamiaru zadeklarowanych przez komponent.
Komponent aplikacji powinien deklarować oddzielne filtry dla każdego unikalnego zadania, które może wykonać. Na przykład jedna aktywność w aplikacji galerii obrazów może mieć 2 filtry: jeden do wyświetlania obrazu, a drugi do jego edytowania. Gdy aktywność się rozpoczyna, sprawdza Intent
i na podstawie informacji w Intent
(np. czy wyświetlać elementy sterujące edytora) decyduje o swoim działaniu.
Każdy filtr intencji jest zdefiniowany przez element <intent-filter>
w pliku manifestu aplikacji, zagnieżdżony w odpowiednim komponencie aplikacji (np. w elemencie <activity>
).
W każdym komponencie aplikacji, który zawiera element <intent-filter>
, wyraźnie ustaw wartość android:exported
.
Ten atrybut wskazuje, czy komponent aplikacji jest dostępny dla innych aplikacji. W niektórych sytuacjach, np. w przypadku aktywności, których filtry intencji zawierają kategorię LAUNCHER
, warto ustawić ten atrybut na true
. W przeciwnym razie bezpieczniej jest ustawić ten atrybut na false
.
Ostrzeżenie: jeśli aktywność, usługa lub odbiornik w aplikacji używa filtrów intencji i nie ma wyraźnie ustawionej wartości parametru android:exported
, aplikacja nie będzie mogła zostać zainstalowana na urządzeniu z Androidem 12 lub nowszym.
W elemencie <intent-filter>
możesz określić typy intencji do zaakceptowania, używając co najmniej jednego z tych 3 elementów:
<action>
- Deklaruje zaakceptowanie działania intencji w atrybucie
name
. Wartość musi być dosłowną wartością ciągu znaków działania, a nie stałą klasy. <data>
- Deklaruje typ akceptowanych danych za pomocą co najmniej 1 atrybutu, który określa różne aspekty identyfikatora URI danych (
scheme
,host
,port
,path
) i typ MIME. <category>
- Deklaruje zaakceptowaną kategorię intencji w atrybucie
name
. Wartość musi być dosłowną wartością ciągu znaków działania, a nie stałą klasy.Uwaga: aby otrzymywać niejawne intencje, musisz uwzględnić kategorię
CATEGORY_DEFAULT
w filtrze intencji. MetodystartActivity()
istartActivityForResult()
traktują wszystkie intencje tak, jakby deklarowały kategorięCATEGORY_DEFAULT
. Jeśli nie zadeklarujesz tej kategorii w filtrze intencji, żadne intencje niejawne nie będą kierowane do Twojej aktywności.
Oto na przykład deklaracja aktywności z filtrem intencji, który umożliwia odbieranie intencji ACTION_SEND
, gdy typ danych to tekst:
<activity android:name="ShareActivity" android:exported="false"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
Możesz utworzyć filtr, który zawiera więcej niż 1 wystąpienie symbolu <action>
, <data>
lub <category>
.
Jeśli tak zrobisz, musisz mieć pewność, że komponent poradzi sobie z dowolną kombinacją tych elementów filtra.
Jeśli chcesz obsługiwać wiele rodzajów intencji, ale tylko w określonych kombinacjach działania, danych i typu kategorii, musisz utworzyć wiele filtrów intencji.
Intencja domyślna jest testowana względem filtra przez porównanie jej z każdym z 3 elementów. Aby intencja została przekazana do komponentu, musi przejść wszystkie 3 testy. Jeśli nie uda się dopasować choćby jednego z nich, system Android nie przekaże intencji do komponentu. Komponent może jednak mieć wiele filtrów intencji, więc intencja, która nie przejdzie przez jeden z nich, może przejść przez inny. Więcej informacji o tym, jak system rozwiązuje intencje, znajdziesz w sekcji poniżej poświęconej rozwiązywaniu intencji.
Ostrzeżenie: używanie filtra intencji nie jest bezpiecznym sposobem na uniemożliwienie innym aplikacjom uruchamiania komponentów. Filtry intencji ograniczają komponent do reagowania tylko na określone rodzaje domniemanych intencji, ale inna aplikacja może potencjalnie uruchomić komponent Twojej aplikacji za pomocą jawnej intencji, jeśli deweloper określi nazwy komponentów.
Jeśli zależy Ci na tym, aby tylko Twoja aplikacja mogła uruchamiać jeden z Twoich komponentów, nie deklaruj filtrów intencji w pliku manifestu. Zamiast tego ustaw atrybut exported
na "false"
dla tego komponentu.
Podobnie, aby uniknąć przypadkowego uruchomienia Service
innej aplikacji, zawsze używaj jawnego zamiaru, aby uruchomić własną usługę.
Uwaga:
w przypadku wszystkich aktywności musisz zadeklarować filtry intencji w pliku manifestu.
Filtry odbiorników transmisji można jednak rejestrować dynamicznie, wywołując metodę
registerReceiver()
. Następnie możesz wyrejestrować odbiornik w unregisterReceiver()
. Dzięki temu aplikacja może nasłuchiwać określonych transmisji tylko przez określony czas, gdy jest uruchomiona.
Przykładowe filtry
Aby zademonstrować niektóre zachowania filtra intencji, oto przykład z pliku manifestu aplikacji do udostępniania w mediach społecznościowych:
<activity android:name="MainActivity" android:exported="true"> <!-- This activity is the main entry, should appear in app launcher --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ShareActivity" android:exported="false"> <!-- This activity handles "SEND" actions with text data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/vnd.google.panorama360+jpg"/> <data android:mimeType="image/*"/> <data android:mimeType="video/*"/> </intent-filter> </activity>
Pierwsza aktywność, MainActivity
, to główny punkt wejścia do aplikacji – aktywność, która otwiera się, gdy użytkownik po raz pierwszy uruchamia aplikację za pomocą ikony w programie uruchamiającym:
- Działanie
ACTION_MAIN
oznacza, że jest to główny punkt wejścia i nie oczekuje żadnych danych intencji. - Kategoria
CATEGORY_LAUNCHER
oznacza, że ikona tej aktywności powinna być umieszczona w menu aplikacji systemu. Jeśli element<activity>
nie określa ikony za pomocą atrybutuicon
, system używa ikony z elementu<application>
.
Aby aktywność była widoczna w menu aplikacji, te 2 elementy muszą być ze sobą powiązane.
Drugie działanie, ShareActivity
, ma ułatwiać udostępnianie tekstu i treści multimedialnych. Użytkownicy mogą przejść do tego działania, nawigując do niego z MainActivity
, ale mogą też przejść do ShareActivity
bezpośrednio z innej aplikacji, która wysyła niejawną intencję pasującą do jednego z 2 filtrów intencji.
Uwaga: typ MIME,
application/vnd.google.panorama360+jpg
, to specjalny typ danych, który określa zdjęcia panoramiczne. Możesz je obsługiwać za pomocą interfejsów API Google
panorama.
Dopasowywanie intencji do filtrów intencji innych aplikacji
Jeśli inna aplikacja jest kierowana na Androida 13 (API na poziomie 33) lub nowszego, może obsługiwać intencję Twojej aplikacji tylko wtedy, gdy pasuje ona do działań i kategorii elementu <intent-filter>
w tej aplikacji. Jeśli system nie znajdzie dopasowania, zgłosi wyjątek ActivityNotFoundException
.
Aplikacja wysyłająca musi obsłużyć ten wyjątek.
Podobnie, jeśli zaktualizujesz aplikację tak, aby była kierowana na Androida 13 lub nowszego, wszystkie intencje pochodzące z aplikacji zewnętrznych będą dostarczane do wyeksportowanego komponentu aplikacji tylko wtedy, gdy będą zgodne z działaniami i kategoriami elementu <intent-filter>
zadeklarowanego przez aplikację. To zachowanie występuje niezależnie od docelowej wersji pakietu SDK aplikacji wysyłającej.
W tych przypadkach dopasowywanie do intencji nie jest wymuszane:
- Intencje dostarczane do komponentów, które nie deklarują żadnych filtrów intencji.
- Intencje pochodzące z tej samej aplikacji.
- Intencje pochodzące z systemu, czyli intencje wysyłane z „identyfikatora UID systemu” (uid=1000). Aplikacje systemowe obejmują
system_server
i aplikacje, które ustawiają wartośćandroid:sharedUserId
naandroid.uid.system
. - Intencje pochodzące z katalogu głównego.
Dowiedz się więcej o dopasowywaniu do intencji.
Korzystanie z intencji oczekującej
Obiekt PendingIntent
jest otoczką obiektu Intent
. Głównym celem PendingIntent
jest przyznanie zagranicznej aplikacji uprawnień do korzystania z zawartego w niej Intent
tak, jakby był on wykonywany w procesie Twojej aplikacji.
Główne przypadki użycia oczekującego zamiaru to:
- Deklarowanie intencji, która ma zostać wykonana, gdy użytkownik podejmie działanie związane z powiadomieniem (
NotificationManager
systemu Android wykonujeIntent
). - Deklarowanie intencji, która ma zostać wykonana, gdy użytkownik wykona działanie w widżecie aplikacji (aplikacja ekranu głównego wykonuje
Intent
). - Deklarowanie intencji, która ma zostać wykonana w określonym czasie w przyszłości (system Android
AlarmManager
wykonujeIntent
).
Podobnie jak każdy obiekt Intent
jest przeznaczony do obsługi przez określony typ komponentu aplikacji (Activity
, Service
lub BroadcastReceiver
), tak samo należy tworzyć obiekt PendingIntent
. Gdy używasz oczekującego zamiaru, aplikacja nie wykonuje go za pomocą wywołania takiego jak startActivity()
. Zamiast tego musisz zadeklarować zamierzony typ komponentu podczas tworzenia elementu PendingIntent
, wywołując odpowiednią metodę tworzenia:
PendingIntent.getActivity()
w przypadkuIntent
, który rozpoczynaActivity
.PendingIntent.getService()
w przypadkuIntent
, który rozpoczynaService
.PendingIntent.getBroadcast()
w przypadkuIntent
, który rozpoczynaBroadcastReceiver
.
O ile Twoja aplikacja nie otrzymuje oczekujących intencji z innych aplikacji, powyższe metody tworzenia PendingIntent
są prawdopodobnie jedynymi metodami, jakich kiedykolwiek będziesz potrzebować.PendingIntent
Każda metoda przyjmuje bieżącą aplikację Context
, element Intent
, który chcesz opakować, oraz co najmniej 1 flagę określającą sposób użycia intencji (np. czy można jej użyć więcej niż raz).
Więcej informacji o używaniu oczekujących intencji znajdziesz w dokumentacji poszczególnych przypadków użycia, np. w przewodnikach po interfejsach API Powiadomienia i Widżety aplikacji.
Określanie zmienności
Jeśli Twoja aplikacja jest kierowana na Androida 12 lub nowszego, musisz określić zmienność każdego obiektu PendingIntent
tworzonego przez aplikację. Aby zadeklarować, że dany obiekt PendingIntent
jest zmienny lub niezmienny, użyj odpowiednio flagi PendingIntent.FLAG_MUTABLE
lub PendingIntent.FLAG_IMMUTABLE
.
Jeśli aplikacja spróbuje utworzyć obiekt PendingIntent
bez ustawienia żadnej flagi zmienności, system zgłosi wyjątek IllegalArgumentException
, a w narzędziu Logcat pojawi się ten komunikat:
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
W miarę możliwości twórz niezmienne oczekujące intencje.
W większości przypadków aplikacja powinna tworzyć niezmienne obiekty PendingIntent
, jak pokazano w tym fragmencie kodu. Jeśli obiekt PendingIntent
jest niezmienny, inne aplikacje nie mogą modyfikować intencji, aby dostosować wynik jej wywołania.
Kotlin
val pendingIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
W niektórych przypadkach użycia wymagane są jednak obiekty modyfikowalne PendingIntent
:
- Obsługa bezpośrednich odpowiedzi w powiadomieniach. Bezpośrednia odpowiedź wymaga zmiany danych klipu w obiekcie PendingIntent powiązanym z odpowiedzią. Zwykle o tę zmianę prosisz, przekazując wartość
FILL_IN_CLIP_DATA
jako flagę do metodyfillIn()
. - Powiązywanie powiadomień z platformą Android Auto za pomocą instancji
CarAppExtender
. - Umieszczanie rozmów w dymkach za pomocą instancji
PendingIntent
. Obiekt modyfikowalnyPendingIntent
umożliwia systemowi zastosowanie odpowiednich flag, takich jakFLAG_ACTIVITY_MULTIPLE_TASK
iFLAG_ACTIVITY_NEW_DOCUMENT
. - Wysyłanie prośby o informacje o lokalizacji urządzenia przez wywołanie interfejsu API
requestLocationUpdates()
lub podobnych interfejsów API. Obiekt modyfikowalnyPendingIntent
umożliwia systemowi dodawanie dodatkowych informacji o intencjach, które reprezentują zdarzenia cyklu życia lokalizacji. Obejmują one zmianę lokalizacji i dostępność dostawcy. - Ustawianie alarmów za pomocą
AlarmManager
. ObiektPendingIntent
z możliwością zmiany umożliwia systemowi dodanie dodatkowego parametruEXTRA_ALARM_COUNT
intencji. Ta dodatkowa informacja przedstawia liczbę uruchomień powtarzającego się alarmu. Dzięki temu dodatkowemu elementowi intencja może dokładnie powiadamiać aplikację o tym, czy powtarzający się alarm został uruchomiony wielokrotnie, np. gdy urządzenie było w trybie uśpienia.
Jeśli aplikacja tworzy obiekt modyfikowalny PendingIntent
, zdecydowanie zalecamy użycie jawnego zamiaru i wypełnienie pola ComponentName
. Dzięki temu, gdy inna aplikacja wywoła PendingIntent
i przekaże kontrolę z powrotem do Twojej aplikacji, zawsze uruchomi się ten sam komponent.
Używanie intencji bezpośrednich w intencjach oczekujących
Aby lepiej określić, jak inne aplikacje mogą używać oczekujących intencji Twojej aplikacji, zawsze umieszczaj oczekującą intencję w intencji jawnej. Aby stosować tę sprawdzoną metodę, wykonaj te czynności:
- Sprawdź, czy pola działania, pakietu i komponentu podstawowej intencji są ustawione.
-
Do tworzenia oczekujących intencji używaj metody
FLAG_IMMUTABLE
, która została dodana w Androidzie 6.0 (poziom interfejsu API 23). Ten flag uniemożliwia aplikacjom, które otrzymująPendingIntent
, wypełnianie brakujących właściwości. Jeśli wartośćminSdkVersion
w Twojej aplikacji jest22
lub niższa, możesz podać informacje o bezpieczeństwie i zgodności razem za pomocą tego kodu:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
Rozpoznawanie intencji
Gdy system otrzyma niejawną intencję rozpoczęcia aktywności, wyszuka najlepszą aktywność dla tej intencji, porównując ją z filtrami intencji na podstawie 3 aspektów:
- Działanie.
- dane (zarówno URI, jak i typ danych);
- Category [Kategoria]:
W sekcjach poniżej opisujemy, jak intencje są dopasowywane do odpowiednich komponentów na podstawie deklaracji filtra intencji w pliku manifestu aplikacji.
Test działania
Aby określić akceptowane działania związane z intencją, filtr intencji może deklarować zero lub więcej elementów <action>
, jak pokazano w tym przykładzie:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
Aby przejść ten filtr, działanie określone w parametrze Intent
musi być zgodne z jednym z działań wymienionych w filtrze.
Jeśli filtr nie zawiera żadnych działań, nie ma niczego, do czego intencja mogłaby pasować, więc wszystkie intencje nie przejdą testu. Jeśli jednak Intent
nie określa działania, test zostanie zaliczony, o ile filtr zawiera co najmniej 1 działanie.
Test kategorii
Aby określić akceptowane kategorie intencji, filtr intencji może zadeklarować zero lub więcej elementów <category>
, jak pokazano w tym przykładzie:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
Aby intencja przeszła test kategorii, każda kategoria w Intent
musi odpowiadać kategorii w filtrze. Nie jest to jednak konieczne – filtr intencji może deklarować więcej kategorii niż określono w Intent
, a Intent
nadal będzie przekazywać informacje. Dlatego intencja bez kategorii zawsze przechodzi ten test, niezależnie od tego, jakie kategorie są zadeklarowane w filtrze.
Uwaga:
Android automatycznie stosuje kategorię CATEGORY_DEFAULT
do wszystkich niejawnych intencji przekazywanych do startActivity()
i startActivityForResult()
.
Jeśli chcesz, aby Twoja aktywność odbierała intencje niejawne, musi ona zawierać kategorię "android.intent.category.DEFAULT"
w filtrach intencji, jak pokazano w poprzednim przykładzie <intent-filter>
.
Test danych
Aby określić akceptowane dane intencji, filtr intencji może deklarować zero lub więcej elementów
<data>
, jak pokazano w tym przykładzie:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
Każdy element <data>
może określać strukturę URI i typ danych (typ MIME).
Każda część identyfikatora URI jest osobnym atrybutem: scheme
, host
, port
i path
:
<scheme>://<host>:<port>/<path>
Poniższy przykład pokazuje możliwe wartości tych atrybutów:
content://com.example.project:200/folder/subfolder/etc
W tym identyfikatorze URI schemat to content
, host to com.example.project
, port to 200
, a ścieżka to folder/subfolder/etc
.
Każdy z tych atrybutów jest opcjonalny w elemencie <data>
, ale istnieją zależności liniowe:
- Jeśli nie podasz schematu, host zostanie zignorowany.
- Jeśli nie podasz hosta, port zostanie zignorowany.
- Jeśli nie podasz schematu ani hosta, ścieżka zostanie zignorowana.
Gdy identyfikator URI w intencji jest porównywany ze specyfikacją identyfikatora URI w filtrze, porównywane są tylko te części identyfikatora URI, które są uwzględnione w filtrze. Na przykład:
- Jeśli filtr określa tylko schemat, wszystkie identyfikatory URI z tym schematem pasują do filtra.
- Jeśli filtr określa schemat i autorytet, ale nie ścieżkę, wszystkie identyfikatory URI z tym samym schematem i autorytetem przejdą filtr niezależnie od ścieżek.
- Jeśli filtr określa schemat, autorytet i ścieżkę, tylko identyfikatory URI o tym samym schemacie, autorytecie i ścieżce przejdą przez filtr.
Uwaga: specyfikacja ścieżki może zawierać symbol wieloznaczny w postaci gwiazdki (*), aby wymagać tylko częściowego dopasowania nazwy ścieżki.
Test danych porównuje zarówno identyfikator URI, jak i typ MIME w intencji z identyfikatorem URI i typem MIME określonym w filtrze. Obowiązują te zasady:
- Intencja, która nie zawiera identyfikatora URI ani typu MIME, przechodzi test tylko wtedy, gdy filtr nie określa żadnych identyfikatorów URI ani typów MIME.
- Intencja, która zawiera identyfikator URI, ale nie ma typu MIME (ani jawnego, ani możliwego do wywnioskowania z identyfikatora URI), przechodzi test tylko wtedy, gdy jej identyfikator URI pasuje do formatu identyfikatora URI filtra, a filtr również nie określa typu MIME.
- Intencja, która zawiera typ MIME, ale nie zawiera identyfikatora URI, przechodzi test tylko wtedy, gdy filtr zawiera ten sam typ MIME i nie określa formatu identyfikatora URI.
- Intencja, która zawiera zarówno identyfikator URI, jak i typ MIME (jawny lub możliwy do wywnioskowania z identyfikatora URI), przechodzi test typu MIME tylko wtedy, gdy ten typ pasuje do typu wymienionego w filtrze. Test identyfikatora URI jest zaliczany, jeśli identyfikator URI pasuje do identyfikatora URI w filtrze lub jeśli ma identyfikator URI
content:
lubfile:
, a filtr nie określa identyfikatora URI. Innymi słowy, komponent obsługuje danecontent:
ifile:
, jeśli jego lista filtrów zawiera tylko typ MIME.
Uwaga: jeśli intencja określa identyfikator URI lub typ MIME, test danych zakończy się niepowodzeniem, jeśli w elemencie <intent-filter>
nie ma elementów <data>
.
Ostatnia reguła, czyli reguła (d), odzwierciedla oczekiwanie, że komponenty mogą pobierać dane lokalne z pliku lub dostawcy treści.
Dlatego ich filtry mogą zawierać tylko typ danych i nie muszą jawnie określać schematów content:
i file:
.
Poniższy przykład pokazuje typowy przypadek, w którym element <data>
informuje Androida, że komponent może pobierać dane obrazu z dostawcy treści i je wyświetlać:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
Filtry, które określają typ danych, ale nie URI, są prawdopodobnie najczęstsze, ponieważ większość dostępnych danych jest udostępniana przez dostawców treści.
Inną popularną konfiguracją jest filtr ze schematem i typem danych. Na przykład element <data>
informuje Androida, że komponent może pobierać dane wideo z sieci, aby wykonać działanie:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
Dopasowywanie do intencji
Intencje są dopasowywane do filtrów intencji nie tylko w celu wykrycia komponentu docelowego do aktywacji, ale także w celu uzyskania informacji o zestawie komponentów na urządzeniu. Na przykład aplikacja Home wypełnia program uruchamiający aplikacje, wyszukując wszystkie aktywności z filtrami intencji, które określają działanie ACTION_MAIN
i kategorię CATEGORY_LAUNCHER
.
Dopasowanie jest możliwe tylko wtedy, gdy działania i kategorie w obiekcie Intent pasują do filtra, co opisano w dokumentacji klasy IntentFilter
.
Aplikacja może używać dopasowywania intencji w sposób podobny do aplikacji Google Home.
Klasa PackageManager
ma zestaw metod query...()
, które zwracają wszystkie komponenty mogące akceptować określony zamiar, oraz podobną serię metod resolve...()
, które określają najlepszy komponent do reagowania na zamiar. Na przykład queryIntentActivities()
zwraca listę wszystkich aktywności, które mogą wykonać intencję przekazaną jako argument, a queryIntentServices()
zwraca podobną listę usług.
Żadna z tych metod nie aktywuje komponentów. Wyświetlają one tylko te, które mogą odpowiadać. Podobna metoda, queryBroadcastReceivers()
, jest dostępna w przypadku odbiorników.