Intent
to obiekt komunikacji, którego możesz użyć, aby poprosić o działanie
z innego komponentu aplikacji.
Choć intencje ułatwiają komunikację między komponentami na kilka sposobów, wyróżniamy trzy
podstawowe przypadki użycia:
- Rozpoczynanie aktywności
Activity
reprezentuje jeden ekran w aplikacji. Możesz rozpocząć nowe wystąpienieActivity
, przekazującIntent
dostartActivity()
. ElementIntent
opisuje aktywność do uruchomienia i zawiera wszystkie niezbędne dane.Jeśli chcesz otrzymać wynik po zakończeniu aktywności, zadzwoń pod numer
startActivityForResult()
. Wynik Twojej aktywności jako osobny obiektIntent
w wywołaniu zwrotnymonActivityResult()
Twojej aktywności. 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 możesz uruchomić usługę dziękiJobScheduler
. Więcej informacji okołoJobScheduler
, zobacz jegoAPI-reference documentation
W przypadku wersji Androida starszych niż 5.0 (poziom interfejsu API 21) możesz uruchomić usługę za pomocą polecenia metod klasy
Service
. Możesz uruchomić usługę, aby wykonać jednorazową operację (np. pobrać plik), przekazującIntent
dostartService()
.Intent
opisuje usługę, która ma zostać uruchomiona, oraz zawiera wszystkie niezbędne dane.Jeśli usługa została zaprojektowana z wykorzystaniem interfejsu klient-serwer, możesz ją powiązać z innego komponentu, przekazując
Intent
dobindService()
. Więcej informacji znajdziesz w przewodniku Usługi. - Przesyłanie transmisji
Wiadomość rozgłaszana to wiadomość, którą może otrzymać dowolna aplikacja. System udostępnia różne komunikatów dotyczących zdarzeń systemowych, takich jak uruchomienie systemu lub rozpoczęcie ładowania urządzenia. Możesz przesłać komunikat 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ć. Powiązane informacje: Interakcje z innymi aplikacjami oraz Udostępnianie treści.
Typy intencji
Istnieją 2 rodzaje intencji:
- Intencje jawne określają, który komponent danej aplikacji spełni intencję, poprzez określenie pełnego parametru
ComponentName
. Zazwyczaj do uruchamiania komponentu w własnej aplikacji używasz wyraźnego zamiaru, ponieważ znasz nazwę klasy aktywności lub usługi, którą chcesz uruchomić. Dla: możesz na przykład rozpocząć w aplikacji nową aktywność w odpowiedzi na działanie użytkownika usługa pobierania pliku w tle. - Intencje ogólne nie wskazują konkretnego komponentu, ale deklarują ogólne działanie, co pozwala komponentowi z innej aplikacji na obsłużenie tej intencji. Jeśli chcesz na przykład pokazać użytkownikowi lokalizację na mapie, możesz użyć niejawnej intencji, by poprosić inną pokazują określoną lokalizację na mapie.
Rysunek 1 przedstawia, jak intencja jest używana podczas uruchamiania aktywności. Jeśli obiekt Intent
wyraźnie podaje nazwę konkretnego komponentu aktywności, system natychmiast uruchamia ten komponent.

Rysunek 1. Intencja pośrednia
dostarczone przez system, aby rozpocząć inne działanie: [1] Działanie A tworzy
Intent
z opisem działania i przekazuje go do startActivity()
. [2] System Android przeszukuje wszystkie aplikacje w celu znalezienia filtra intencji pasującego do intencji. Po znalezieniu dopasowania [3] system
rozpoczyna pasującą aktywność (działanie B) przez wywołanie metody onCreate()
i przekazywanie jej Intent
.
Gdy używasz intencji niejawnej, system Android znajduje odpowiedni komponent, by uruchomić
porównując zawartość intencji z filtrami intencji zadeklarowanych w pliku manifestu innych aplikacji na stronie
urządzenia. Jeśli intencja pasuje do filtra intencji, system uruchamia ten komponent i go dostarcza.
obiekt Intent
. Jeśli kilka filtrów intencji jest zgodnych, system wyświetli okno dialogowe, aby użytkownik mógł wybrać aplikację, której ma użyć.
Filtr intencji to wyrażenie w pliku manifestu aplikacji, które określa typy intencji, które komponent chce otrzymywać. Na przykład zadeklarowanie filtra intencji dla działania umożliwiasz innym aplikacjom bezpośrednie rozpoczęcie Twojej aktywności z określonym zamiarem. Podobnie, jeśli nie zadeklarujesz żadnych filtrów intencji dla aktywności, może ona zostać uruchomiona tylko z wyraźną intencją.
Uwaga: aby mieć pewność, że aplikacja jest bezpieczna, zawsze
użyj jednoznacznego
przy uruchamianiu funkcji Service
i nie
zadeklarować filtry intencji dla usług. Użycie intencji ogólnej do uruchomienia usługi
zagraża bezpieczeństwu, ponieważ nie można mieć pewności, która usługa zareaguje na intencję,
a użytkownik nie widzi, która usługa się uruchamia. Począwszy od Androida 5.0 (poziom interfejsu API 21) system zgłasza wyjątek, jeśli wywołasz bindService()
z użyciem niejawnej intencji.
Budowanie zamiaru
Obiekt Intent
zawiera informacje, których system Android używa do określenia, który komponent uruchomić (np. dokładną nazwę komponentu lub kategorię komponentu, który powinien otrzymać intencję), a także informacje, których komponent odbiorczy używa do prawidłowego wykonania działania (np. działanie do wykonania i dane, na których ma ono polegać).
Główne informacje zawarte w pliku Intent
:
- Nazwa komponentu
- Nazwa komponentu, który ma zostać uruchomiony.
Jest to element opcjonalny, ale kluczowa informacja, która sprawia, że chęć jest wyraźna, co oznacza, że chęć powinna być dostarczana tylko do komponentu aplikacji zdefiniowanego przez nazwę komponentu. Bez nazwy komponentu intencja jest domyślna, a system decyduje, który komponent powinien ją otrzymać na podstawie innych informacji o intencji (takich jak działanie, dane i kategoria, opisane poniżej). Jeśli chcesz uruchomić konkretny komponent w aplikacji, musisz podać jego nazwę.
Uwaga: gdy uruchamiasz
Service
, zawsze określaj nazwę komponentu. W przeciwnym razie nie masz pewności, która usługa zareaguje na intencję, a użytkownik nie będzie mógł zobaczyć, która usługa się uruchamia.To pole w
Intent
to obiektComponentName
, który możesz określić, podając w pełni kwalifikowaną nazwę klasy komponentu docelowego, w tym nazwę pakietu aplikacji, na przykładcom.example.ExampleActivity
. Nazwa komponentu może być ustawiana za pomocą funkcjisetComponent()
,setClass()
,setClassName()
lub konstruktoraIntent
. - Działanie
- Ciąg tekstowy określający ogólne działanie do wykonania (np. view lub pick).
W przypadku intencji transmisji jest to działanie, które miało miejsce i jest raportowane. Działanie w dużej mierze określa, jak sformułowana jest reszta intencji, w szczególności informacje zawarte w danych i elementach dodatkowych.
Możesz określić własne działania do użycia przez intencje w aplikacji (lub do użycia przez inne aplikacje do wywoływania komponentów w aplikacji), ale zwykle określasz stałe działania zdefiniowane przez klasę
Intent
lub inne klasy frameworka. Oto kilka typowe czynności związane z rozpoczynaniem aktywności:ACTION_VIEW
- Używaj 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
- Zwany też zamierzaniem udostępniania. Należy go używać w zamierzaniu
startActivity()
, gdy masz dane, które użytkownik może udostępnić za pomocą innej aplikacji, np. aplikacji pocztowej lub aplikacji do udostępniania w mediach społecznościowych.
Więcej informacji znajdziesz w dokumentacji zajęć
Intent
. stałe, które definiują działania ogólne. Inne działania są definiowane w innych miejscach w ramach Androida, np. wSettings
w przypadku działań, które otwierają określone ekrany w aplikacji Ustawienia systemu.Działanie możesz określić w przypadku intencji za pomocą
setAction()
lub konstruktoraIntent
.Jeśli określisz własne działania, pamiętaj o podaniu nazwy pakietu aplikacji jak w tym przykładzie:
- Dane
- Identyfikator URI (obiekt
Uri
), który odwołuje się do danych do podejmowanych w związku z typu MIME. Typ danych jest zwykle określany przez działanie związane z zamiarem. Jeśli na przykład działanie toACTION_EDIT
, dane powinny zawierać URI dokumentu do edycji.Podczas tworzenia intencji często warto określić typ danych (typ MIME) oprócz URI. Na przykład aktywność, która może wyświetlać obrazy, prawdopodobnie nie będzie w stanie odtworzyć plik audio, chociaż formaty URI mogą być podobne. Określenie typu MIME danych ułatwia system znajduje najlepszy komponent, który dostanie intencję. Jednak typ MIME można czasem wywnioskować na podstawie identyfikatora URI, zwłaszcza jeśli dane są Identyfikator URI
content:
. Identyfikator URIcontent:
wskazuje, że dane znajdują się na urządzeniu i kontrolowane przezContentProvider
, dzięki czemu 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 te parametry za pomocą parametrusetDataAndType()
.Uwaga: jeśli chcesz ustawić zarówno URI, jak i typ MIME, nie wywołuj funkcji
setData()
anisetType()
, ponieważ każda z nich anuluje wartość drugiej. Zawsze używajsetDataAndType()
do ustawienia obydwu źródeł Identyfikator URI i typ MIME. - Kategoria
- Ciąg tekstowy 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
- Docelowa aktywność może zostać uruchomiona przez przeglądarkę w celu wyświetlenia danych do którego odwołuje się link, np. zdjęcie lub wiadomość e-mail.
CATEGORY_LAUNCHER
- Aktywność to początkowa aktywność w ramach zadania i jest widoczna w program uruchamiający aplikacje.
Pełną listę kategorii znajdziesz w opisie klasy
Intent
.Kategorię możesz określić za pomocą tagu
addCategory()
.
Wymienione powyżej właściwości (nazwa komponentu, działanie, dane i kategoria) stanowią cechy definiujące intencję. Odczytując te właściwości, system Android jest w stanie określić komponent aplikacji, który ma zostać uruchomiony. Może ona jednak zawierać dodatkowe informacje, które nie wpływają na sposób jej przekształcania w element 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 URI danych, tak też niektóre działania korzystają z określonych dodatków.
Dodatkowe dane możesz dodawać za pomocą różnych metod
putExtra()
, z których każda przyjmuje 2 parametry: nazwę klucza i wartość. Możesz też utworzyć obiektBundle
ze wszystkimi dodatkowymi danymi, a potem umieścićBundle
w obiekcieIntent
za pomocąputExtras()
.Na przykład podczas tworzenia zamiaru wysłania e-maila z
ACTION_SEND
, możesz określić adresata to za pomocą atrybutuEXTRA_EMAIL
i określ subject za pomocą atrybutuEXTRA_SUBJECT
klawisz.Klasa
Intent
określa wiele stałychEXTRA_*
dla ustandaryzowanych typów danych. Jeśli musisz zadeklarować dodatkowe klucze (dla intencji, które otrzymuje Twoja aplikacja), pamiętaj, aby dołączyć nazwę pakietu aplikacji jako prefiks, jak w tym przykładzie:const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Uwaga: nie używaj właściwości
Parcelable
ani daneSerializable
podczas wysyłania oczekiwanej intencji kolejną aplikację do odbioru. Jeśli aplikacja próbuje uzyskać dostęp do danych w obiekcieBundle
, ale nie próbuje dostępu do klasy spakowanej lub serializowanej, system podnosiRuntimeException
- Flagi
- Flagi są zdefiniowane w klasie
Intent
, które działają jako metadane intencji. Flagi mogą instruować system Android, jak uruchomić działanie (na przykład które zadanie aktywność powinna należeć ) oraz jak postępować z nimi po uruchomieniu (np. czy znajduje się na liście ostatnich aktywności).Więcej informacji znajdziesz w metodzie
setFlags()
.
Przykładowa intencja bezpośrednia
Wyraźna intencja to intencja, której używasz do uruchamiania określonego komponentu aplikacji, np. określonej aktywności lub usługi w aplikacji. Aby utworzyć wyraźną intencję, zdefiniuj nazwę komponentu dla obiektu Intent
. Pozostałe właściwości intencji są opcjonalne.
Jeśli np. w aplikacji utworzysz usługę o nazwie DownloadService
, która ma pobierać pliki z internetu, możesz ją uruchomić za pomocą tego kodu:
// 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)
// 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);
Intent(Context, Class)
Konstruktor dostarcza aplikację Context
oraz
do obiektu Class
. W takim przypadku ten zamiar wyraźnie uruchamia klasę DownloadService
w aplikacji.
Więcej informacji o tworzeniu i uruchamianiu usługi znajdziesz w przewodniku Usługi.
Przykładowa intencja ogólna
Intencja niejawna określa działanie, które może wywołać dowolną aplikację na urządzeniu, która może wykonanie działania. Użycie intencji niejawnej jest przydatne, gdy aplikacja nie może wykonać ale inne aplikacje prawdopodobnie już tak i chcesz, aby to użytkownik sam wybierał, której z nich chce 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 intent startActivity()
, użytkownik może wybrać aplikację, za pomocą której udostępni treści.
// 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. }
// 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łana zostanie metoda startActivity()
, system sprawdza wszystkie zainstalowane aplikacje, aby określić, które z nich mogą obsłużyć ten rodzaj inencji (intencję z działaniem ACTION_SEND
i danymi w formacie „text/plain”). Jeśli istnieje tylko jedna aplikacja, która może ją obsłużyć, otwiera się od razu i otrzymuje
intencji. Jeśli inne aplikacje nie są w stanie go obsłużyć, wychwytuje
ActivityNotFoundException
które występują. Jeśli wiele działań akceptuje ten zamiar, system wyświetla okno podobne do tego na rysunku 2, aby użytkownik mógł wybrać aplikację.
Więcej informacji o uruchamianiu innych aplikacji znajdziesz w przewodniku przesyłania użytkownika do innej aplikacji.

Rysunek 2. Okno wyboru.
Wymuszanie wyboru aplikacji
Jeśli istnieje więcej niż 1 aplikacja, która reaguje na Twoją domyślną intencję, użytkownik może wybrać aplikację, której ma używać domyślnie. Możliwość wyboru wartości domyślnej jest przydatna przy wykonywaniu działania, Pewnie chce używać tej samej aplikacji za każdym razem, na przykład podczas otwierania strony internetowej (użytkownicy często preferuje tylko jedną przeglądarkę).
Jeśli jednak wiele aplikacji może odpowiadać na dany zamiar, a użytkownik może chcieć za każdym razem korzystać z innej aplikacji, należy wyświetlić okno wyboru. W oknie wyboru użytkownik musi wybrać aplikację, której ma użyć do wykonania danej czynności (nie może wybrać aplikacji domyślnej). Jeśli na przykład Twoja aplikacja wykonuje działanie „udostępnij” za pomocą akcji ACTION_SEND
, użytkownicy mogą chcieć udostępnić plik za pomocą innej aplikacji w zależności od bieżącej sytuacji. Zawsze używaj okna wyboru, jak pokazano na rysunku 2.
Aby wyświetlić selektor, utwórz pole Intent
przy użyciu createChooser()
i przekaż go do startActivity()
, jak pokazano w przykładzie poniżej.
Ten przykład wyświetla okno z listą aplikacji, które odpowiadają intencji przekazanej metodzie createChooser()
, i używa dostarczonego tekstu jako tytułu okna.
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) }
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 uruchamiania niebezpiecznych intencji
Aplikacja może uruchamiać intencje nawigacji między komponentami, lub wykonać działanie w imieniu innej aplikacji. Aby zwiększyć bezpieczeństwo platformy, Android 12 (poziom interfejsu API 31) i nowsze oferują funkcję debugowania, która ostrzega przed jeśli aplikacja wykonuje niebezpieczne uruchomienie intencji. Aplikacja może na przykład wykonanie niebezpiecznego uruchomienia intencji zagnieżdżonej, która jest przekazywana jako dodatkowy w innej intencji.
Jeśli aplikacja wykona obie te czynności, system wykryje uruchomienie intencji i naruszenie zasad StrictMode następuje:
- Aplikacja oddziela zagnieżdżoną intencję od dodatkowych elementów intencji.
- Aplikacja natychmiast uruchamia aplikację
komponentza pomocą tej zagnieżdżonej intencji,
np. przekazanie intencji
startActivity()
,startService()
lubbindService()
Więcej informacji o tym, jak wykrywać tę sytuację i wprowadzać zmiany w aplikacji, znajdziesz w poście na blogu na temat zagnieżdżania poleceń na Androidzie na Medium.
Sprawdzanie, czy nie są uruchamiane niebezpieczne intencje
Aby sprawdzić, czy w aplikacji nie są uruchamiane niebezpieczne intencje, podczas konfigurowania VmPolicy
wywołaj funkcję detectUnsafeIntentLaunch()
, jak pokazano w tym fragmencie kodu. Jeśli aplikacja wykryje naruszenie zasad trybu ścisłego, możesz zatrzymać jej działanie, aby chronić potencjalnie poufne informacje.
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
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 niebezpiecznej intencji i naruszenia zasad trybu ścisłego, stosuj te sprawdzone metody.
Skopiuj tylko niezbędne dodatki i wykonuj odpowiednie działania
dotyczące higieny i weryfikacji. Aplikacja może skopiować dodatki z jednej intencji do
innej intencji, która służy do uruchamiania nowego komponentu. Dzieje się tak, gdy
wywołania z aplikacji
putExtras(Intent)
lub
putExtras(Bundle)
Jeśli aplikacja wykonuje jedną z tych operacji, skopiuj tylko dodatki, które
którego oczekuje komponent odbierający. Jeśli inna intencja (która otrzymuje kopię)
uruchamia komponent, który nie jest
wyeksportowane, oczyszczone
sprawdzić dodatki przed skopiowaniem ich do intencji, która uruchamia
.
Nie eksportuj niepotrzebnie komponentów aplikacji. Jeśli na przykład
zamierza uruchomić komponent aplikacji przy użyciu wewnętrznej zagnieżdżonej intencji, ustaw ten
android:exported
komponentu do false
.
Zamiast zagnieżdżonego zamiaru używaj PendingIntent
. Dzięki temu, gdy inna aplikacja rozpakuje pakiet PendingIntent
zawierający Intent
, może uruchomić PendingIntent
, korzystając z tożsamości Twojej aplikacji. Ta konfiguracja umożliwia innej aplikacji bezpieczne uruchamianie w Twojej aplikacji dowolnego komponentu, w tym niewyeksportowanego.
Diagram na rysunku 2 pokazuje, jak system przekazuje kontrolę z Twojej aplikacji (klienta) do innej aplikacji (usługi) i z powrotem do Twojej aplikacji:
- Twoja aplikacja tworzy intencję, która wywołuje aktywność w innej aplikacji. W ramach tej intencji dodajesz obiekt
PendingIntent
jako dodatkowy. Ta oczekująca intencja wywołuje komponent w aplikacji, który nie jest eksportowany. - Po otrzymaniu intencji Twojej aplikacji inna aplikacja wyodrębnia zagnieżdżony obiekt
PendingIntent
. - Inna aplikacja wywołuje metodę
send()
obiektuPendingIntent
. - Po przekazaniu sterowania aplikacji system wywołuje oczekującą intencję przy użyciu kontekstu aplikacji.
Rysunek 2. Schemat komunikacji między aplikacjami podczas korzystania z zagnieżdżonego oczekującego elementu intencji.
Odbieranie intencji ogólnej
Aby reklamować intencje pośrednie, które może docierać do aplikacji, zadeklaruj co najmniej 1 filtr intencji
każdego komponentu aplikacji za pomocą tagu <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 przekazuje do komponentu aplikacji domyślną intencję tylko wtedy, gdy intencję można przepuścić przez jeden z Twoich filtrów intencji.
Uwaga: wyraźna intencja jest zawsze dostarczana do celu niezależnie od deklarowanych przez komponent filtrów intencji.
Składnik aplikacji powinien deklarować osobne filtry dla każdego niepowtarzalnego zadania, które może wykonać.
Na przykład jedna aktywność w aplikacji z galeria zdjęć może mieć 2 filtry: jeden do wyświetlania obrazu i drugi do jego edycji. Gdy aktywność się rozpocznie,
sprawdza Intent
i na podstawie tych informacji decyduje, jak ma się zachować
w elemencie Intent
(np. aby wyświetlić elementy sterujące edytora).
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>
,
jawnie ustaw wartość dla
android:exported
Ten atrybut wskazuje, czy składnik aplikacji jest dostępny dla innych aplikacji. W niektórych
takich jak działania, których filtry intencji zawierają
LAUNCHER
kategorii, warto ustawić ten atrybut na true
. W przeciwnym razie bezpieczniej jest ustawić ten atrybut na false
.
Ostrzeżenie: jeśli aktywność, usługa lub komunikat
Odbiorca w Twojej aplikacji używa filtrów intencji i nie ustawia bezpośrednio wartości
w systemie android:exported
nie można zainstalować aplikacji na urządzeniu, które
ma system Android 12 lub nowszy,
W narzędziu <intent-filter>
możesz określić typ akceptowanych intencji
tych 3 elementów:
<action>
- W atrybucie
name
deklaruje przyjęte działanie intencji. Wartość musi być dosłowną wartością ciągu działania, a nie stałą klasy. <data>
- Określa typ akceptowanych danych za pomocą co najmniej jednego atrybutu, który określa różne aspekty identyfikatora URI danych (
scheme
,host
,port
,path
) i typ MIME. <category>
- Określa kategorię intencji zaakceptowaną w atrybucie
name
. Wartość musi być literałem wartości ciągu działania, a nie stałą klasy.Uwaga: aby otrzymywać intencje pośrednie, musi zawierać
CATEGORY_DEFAULT
kategoria w filtrze intencji. MetodystartActivity()
istartActivityForResult()
traktuje wszystkie intencje tak, jakby zadeklarowali kategorięCATEGORY_DEFAULT
. Jeśli nie zadeklarujesz tej kategorii w filtrze intencji, żadne intencje niejawne nie będą kierować Twojej aktywności.
Oto na przykład deklaracja aktywności z filtrem intencji, która ma odbierać intencję 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ęp <action>
, <data>
lub <category>
.
Jeśli to zrobisz, musisz mieć pewność, że komponent obsługuje wszystkie
kombinacji tych elementów filtra.
Gdy chcesz obsługiwać różne rodzaje intencji, ale tylko w konkretnych kombinacjach działania, danych i typu kategorii, musisz utworzyć kilka filtrów intencji.
Intencję niejawną testuje się za pomocą filtra, porównując intencję z każdym trzech elementów. Aby intencja mogła zostać dostarczona do komponentu, musi przejść wszystkie 3 testy. Jeśli nie uda się dopasować nawet jednego z nich, system Android nie przekaże intencji do danego komponentu. Składnik może jednak mieć wiele filtrów intencji, więc intencja, która nie przejdzie przez jeden z nich, może zostać przepuszczona przez inny. Więcej informacji o tym, jak system rozpoznaje intencje, znajdziesz w sekcji poniżej. o rozwiązaniach intencji.
Uwaga: użycie filtra intencji nie jest bezpiecznym sposobem zapobiegania uruchamianiu innych aplikacji
swoje komponenty. Chociaż filtry intencji ograniczają działanie komponentu tylko do określonych rodzajów domniemanych intencji, inna aplikacja może uruchomić komponent Twojej aplikacji, używając do tego wyraźnej 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 w manifeście żadnych filtrów intencji. Zamiast tego skonfiguruj parametr
Atrybut exported
do "false"
dla tego komponentu.
Aby uniknąć przypadkowego uruchomienia Service
innej aplikacji, zawsze używaj wyraźnego zamiaru do uruchamiania własnej usługi.
Uwaga:
W przypadku wszystkich działań musisz zadeklarować filtry intencji w pliku manifestu.
Filtry odbiorników można jednak rejestrować dynamicznie przez wywołanie
registerReceiver()
Potem możesz wyrejestrować odbiorcę w unregisterReceiver()
. Dzięki temu aplikacja będzie mogła
aby nasłuchiwać określonych transmisji tylko przez określony czas, gdy aplikacja
jest uruchomiony.
Przykładowe filtry
Aby zademonstrować niektóre zachowania filtra intencji, podajemy przykład pliku manifestu aplikacji do udostępniania treści 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 aplikacji,
otwiera się, gdy użytkownik po raz pierwszy uruchomi aplikację z ikoną programu uruchamiającego:
- Działanie
ACTION_MAIN
wskazuje, że jest to główny punkt wejścia i nie oczekuje żadnych danych intencji. - Kategoria
CATEGORY_LAUNCHER
wskazuje, że ikona tej aktywności powinna znajdować się w Menu z aplikacjami systemu. Jeśli element<activity>
nie wskaże ikony z oznaczeniemicon
, system użyje ikony z<application>
.
Aby aktywność była widoczna w Menu z aplikacjami, te 2 elementy muszą być sparowane.
Druga aktywność (ShareActivity
) ma ułatwić udostępnianie tekstu i multimediów
treści. Użytkownicy mogą przejść do tej czynności z poziomu MainActivity
, ale mogą też otworzyć ShareActivity
bezpośrednio z innej aplikacji, która wysyła niejawne działanie pasujące 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.
dopasowywać intencje do filtrów intencji innych aplikacji;
Jeśli inna aplikacja jest kierowana na Androida 13 (poziom interfejsu API 33) lub nowszego, może obsłużyć intencję Twojej aplikacji tylko wtedy, gdy Twoja intencja pasuje do działań i kategorii elementu <intent-filter>
w tej innej aplikacji. Jeśli system nie znajdzie dopasowania, rzuci błąd ActivityNotFoundException
.
Aplikacja wysyłająca musi obsługiwać
ten wyjątek.
Podobnie dzieje się, gdy zaktualizujesz aplikację tak, aby była kierowana na Androida 13.
wszystkie intencje pochodzące z aplikacji zewnętrznych są przekazywane
eksportowany komponent aplikacji tylko wtedy, gdy intencja pasuje do działań
kategorii deklarowanego przez aplikację elementu <intent-filter>
. Takie zachowanie występuje niezależnie od docelowej wersji pakietu SDK aplikacji wysyłającej.
W tych sytuacjach dopasowywanie intencji nie jest wymuszane:
- Intencje dostarczone 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 „system UID” (uid=1000). Do aplikacji systemowych należą
system_server
oraz aplikacje z ustawieniemandroid:sharedUserId
doandroid.uid.system
. - Intencje pochodzące z poziomu roota.
Dowiedz się więcej o dopasowywaniu intencji.
Używasz intencji oczekującej
Obiekt PendingIntent
to otoka wokół obiektu Intent
. Głównym celem PendingIntent
jest udzielenie aplikacji zewnętrznej uprawnień do używania zawartego w niej Intent
tak, jakby był on wykonywany w ramach procesu aplikacji.
Główne przypadki użycia oczekującego zamiaru to:
- Zadeklarowanie zamiaru, który ma być wykonany, gdy użytkownik wykona działanie związane z Twoim powiadomieniem (
NotificationManager
systemu Androida wykonuje działanieIntent
). - Deklaracja zamiaru wykonania, gdy użytkownik wykona działanie
Widżet aplikacji
(aplikacja ekranu głównego uruchamia
Intent
). - Oświadczenie o intencji do wykonania w określonym czasie w przyszłości (
AlarmManager
systemu Androida wykonujeIntent
).
Tak jak każdy obiekt Intent
jest przeznaczony do obsługi
typ komponentu aplikacji (Activity
, Service
lub
BroadcastReceiver
), więc także PendingIntent
musi być
stworzonych w ten sam sposób. Gdy używasz intencji oczekującej, aplikacja nie
wykonaj intencję za pomocą wywołania takiego jak startActivity()
. Zamiast tego musisz zadeklarować odpowiedni typ komponentu podczas tworzenia elementu PendingIntent
, wywołując odpowiednią metodę kreatora:
PendingIntent.getActivity()
zaIntent
, który rozpoczyna sięActivity
.PendingIntent.getService()
zaIntent
, który rozpoczyna sięService
.PendingIntent.getBroadcast()
dlaIntent
, który rozpoczynaBroadcastReceiver
.
O ile aplikacja nie otrzymuje oczekujących intencji z innych aplikacji,
powyższe metody tworzenia PendingIntent
są prawdopodobnie jedynymi
PendingIntent
metod, których kiedykolwiek będziesz potrzebować.
Każda metoda przyjmuje bieżącą aplikację Context
, Intent
, którą chcesz opakować, oraz co najmniej 1 flagę, która określa sposób użycia intencji (np. czy można jej użyć więcej niż raz).
Więcej informacji o korzystaniu z intencji oczekujących znajdziesz w dokumentacji poszczególnych odpowiednich przypadków użycia, takich jak Powiadomienia i interfejsów App Widgets.
Określ mutowalność
Jeśli Twoja aplikacja jest kierowana na Androida 12 lub nowszego, musisz określić zmienność każdego obiektu PendingIntent
, który tworzy. Zadeklarowanie, że
jeśli dany obiekt PendingIntent
jest zmienny, użyj funkcji
PendingIntent.FLAG_MUTABLE
lub
PendingIntent.FLAG_IMMUTABLE
flaga.
Jeśli aplikacja próbuje utworzyć obiekt PendingIntent
bez ustawienia flagi zmienności system zwraca
IllegalArgumentException
oraz
w Logcat pojawi się następujący 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 niemodyfikowalne oczekujące intencje
W większości przypadków aplikacja powinna tworzyć stałe obiekty PendingIntent
, jak
w poniższym fragmencie kodu. Jeśli obiekt PendingIntent
jest niezmienny, inne aplikacje nie mogą modyfikować intencji w celu dostosowania wyniku wywołania intencji.
val pendingIntent = PendingIntent.getActivity(applicationContext,REQUEST_CODE , intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),REQUEST_CODE , intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
W niektórych przypadkach wymagane są jednak obiekty PendingIntent
, które można zmieniać:
- Obsługa działań bezpośrednich w powiadomieniach. Odpowiedź bezpośrednia wymaga zmiany danych klipu w obiekcie PendingIntent powiązanym z odpowiedzią. Zwykle prośba o tą zmianę jest przekazywana przez podanie wartości
FILL_IN_CLIP_DATA
jako flagi do metodyfillIn()
. - Powiązanie powiadomień ze platformą Android Auto przy użyciu instancji
CarAppExtender
- Umieszczanie rozmów w dymkach przy użyciu instancji
z
PendingIntent
. Zmienny obiektPendingIntent
umożliwia stosowanie zmian przez system odpowiednie flagi, takie jakFLAG_ACTIVITY_MULTIPLE_TASK
orazFLAG_ACTIVITY_NEW_DOCUMENT
- Wysyłanie żądania informacji o lokalizacji urządzenia przez wywołanie interfejsu
requestLocationUpdates()
lub podobnego. Zmienny obiektPendingIntent
umożliwia systemowi dodawanie dodatkowych informacji o intencji, które reprezentują zdarzenia cyklu życia lokalizacji. Te zdarzenia obejmują zmianę lokalizacji i usługodawcy. - Planuję alarmy za pomocą
AlarmManager
. Zmienny obiektPendingIntent
pozwala systemowi dodać dodatkowy elementEXTRA_ALARM_COUNT
intencji. Ten dodatek przedstawia liczbę powtórzeń alarmu. Dzięki temu intencja może dokładnie powiadomić w aplikacji określa, czy powtarzający się alarm uruchomił się wielokrotnie, np. kiedy urządzenie było uśpione.
Jeśli Twoja aplikacja tworzy zmienny obiekt PendingIntent
, zdecydowanie zalecamy użycie wyraźnego zamiaru i wypełnienie pola ComponentName
. Dzięki temu za każdym razem,
inna aplikacja wywołuje PendingIntent
i przekazuje kontrolę z powrotem do aplikacji,
zawsze uruchamia się ten sam komponent aplikacji.
Używanie intencji bezpośrednich w intencjach oczekujących
Aby lepiej określić, jak inne aplikacje mogą korzystać z oczekujących intencji Twojej aplikacji, zawsze otaczaj oczekującą intencję intencją jawną. Aby zastosować tę sprawdzoną metodę, wykonaj te czynności:
- Sprawdź, czy działanie, pakiet i pola komponentu intencji podstawowej ustawienia.
-
Użyj domeny
FLAG_IMMUTABLE
, dodane w Androidzie 6.0 (poziom interfejsu API 23) w celu utworzenia intencji oczekujących. Ten parametr uniemożliwia aplikacjom, które otrzymują intencjęPendingIntent
, wypełnianie brakujących właściwości. JeśliminSdkVersion
Twojej aplikacji jest22
lub mniejszy, możesz zapewnić bezpieczeństwo i zgodność, używając tego kodu:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
Rozwiązywanie intencji
Gdy system otrzymuje ukrytą intencję rozpoczęcia działania, wyszukuje najlepsze działanie dla intencji, porównując je z filtrami intencji na podstawie 3 aspektów:
- Działanie.
- dane (identyfikator URI i typ danych).
- Category [Kategoria]:
W sekcjach poniżej opisano, jak intencje są dopasowywane do odpowiednich komponentów zgodnie z deklaracją filtra intencji w pliku manifestu aplikacji.
Test działania
Aby określić akceptowane działania związane z zamiarem, filtr zamiaru może zawierać 0 lub więcej elementów <action>
, jak 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 polu Intent
musi pasować do jednego z działań wymienionych w filtrze.
Jeśli filtr nie zawiera żadnych działań, intencja nie ma do czego się dopasować, więc wszystkie intencje nie spełniają kryteriów. Jeśli jednak Intent
nie określa działania, test przechodzi test, dopóki filtr
zawiera co najmniej jedno działanie.
Testowanie kategorii
Aby można było określić akceptowane kategorie intencji, filtr intencji może zadeklarować zero lub więcej.
<category>
zgodnie z tym przykładem:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
Aby można było zaliczyć test kategorii, każda kategoria w: Intent
musi pasować do kategorii w filtrze. Odwrotna zależność nie jest konieczna – filtr intencji może deklarować więcej kategorii niż określono w Intent
, a Intent
nadal będzie spełniać wymagania. Zamiar bez kategorii
zawsze zalicza ten test niezależnie od tego, jakie kategorie 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 niejawne intencje, musi zawierać kategorię "android.intent.category.DEFAULT"
w swoich filtrach intencji, jak pokazano w poprzednim przykładzie <intent-filter>
.
Test danych
Aby określić dane o zaakceptowanych intencjach, filtr intencji może zadeklarować zero lub więcej
<data>
zgodnie z tym przykładem:
<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ę identyfikatora URI i typ danych (typ danych MIME).
Każda część identyfikatora URI jest osobnym atrybutem: scheme
, host
, port
i path
:
<scheme>://<host>:<port>/<path>
Przykład poniżej 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 określisz schematu, host zostanie zignorowany.
- Jeśli nie podasz hosta, port będzie ignorowany.
- Jeśli nie określisz ani schematu, ani hosta, ścieżka zostanie zignorowana.
Gdy identyfikator URI w intencji jest porównywany ze specyfikacją identyfikatora URI w filtrze, jest porównywany tylko z częściami identyfikatora URI zawartymi w filtrze. Na przykład:
- Jeśli filtr określa tylko schemat, pasują do niego wszystkie identyfikatory URI z tym schematem użyj filtra.
- Jeśli filtr określa schemat i urząd, ale nie ścieżkę, wszystkie identyfikatory URI o tym samym schemacie i właściwości przechodzą filtr niezależnie od ich ścieżek.
- Jeśli filtr określa schemat, urząd i ścieżkę, tylko identyfikatory URI z tym samym schematem, autorytet i ścieżka przez filtr.
Uwaga: specyfikacja ścieżki może zawierać symbol wieloznaczny gwiazdka (*), aby wymagać tylko częściowego dopasowania nazwy ścieżki.
Test danych porównuje identyfikator URI i typ MIME w intencji z identyfikatorem URI i typ MIME określony w filtrze. Oto zasady:
- Intencja, która nie zawiera ani identyfikatora URI, ani typu MIME, przekazuje test odbywa się tylko wtedy, gdy filtr nie określa żadnych identyfikatorów URI ani typów MIME.
- Intencje zawierające identyfikator URI, ale nietyp MIME (ani jawny, ani niewynikający z identyfikatora URI) przechodzą test tylko wtedy, gdy identyfikator URI jest zgodny z formatem identyfikatora URI filtra, a filtr nie określa typu MIME.
- Intencje zawierające typ MIME, ale nie URI, przechodzą test tylko wtedy, gdy filtr zawiera ten sam typ MIME i nie określa formatu URI.
- intencja zawierająca zarówno identyfikator URI, jak i typ MIME (jawną lub możliwą do wywnioskowania na podstawie
URI) przekazuje część testu dotyczącą typu MIME tylko wtedy, gdy
typ pasuje do typu wymienionego w filtrze. Przechodzi część testu dotyczącą identyfikatora URI, jeśli jego identyfikator URI pasuje do identyfikatora URI w filtrze lub jeśli ma identyfikator URI
content:
lubfile:
, a filtr nie określa identyfikatora URI. Inaczej mówiąc, komponent jest uznawany za obsługujący danecontent:
ifile:
, jeśli jego filtry zawierają tylko typ MIME.
Uwaga: jeśli intencja określa identyfikator URI lub typ MIME, test danych
kończy się niepowodzeniem, jeśli <intent-filter>
nie zawiera żadnych elementów <data>
.
Ostatnia reguła (d) odzwierciedla oczekiwanie, że komponenty mogą pobierać dane lokalne z pliku lub dostawcy treści.
Dlatego filtry mogą uwzględniać tylko typ danych i nie muszą
nadaj schematom content:
i file:
.
Ten przykład pokazuje typowy przypadek, w którym element <data>
informuje Androida, że komponent może pobierać dane obrazu z treści
dostawcy i wyświetl go:
<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 dostarczana przez dostawców treści.
Inną typową konfiguracją jest filtr ze schematem i typem danych. Na przykład element <data>
, taki jak ten, 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 intencji
Intencje są dopasowywane do filtrów intencji nie tylko po to, aby wykryć docelowy komponent do aktywacji, ale też po to, aby dowiedzieć się czegoś o zbiorze komponentów na urządzeniu. Na przykład aplikacja Home wypełnia menu uruchamiania aplikacji, wyszukując wszystkie aktywności z filtrami intencji, które określają ACTION_MAIN
działanie i CATEGORY_LAUNCHER
kategorię.
Dopasowanie następuje tylko wtedy, gdy działania i kategorie w intencji pasują do filtra, zgodnie z opisem w dokumentacji klasy IntentFilter
.
Aplikacja może używać dopasowania intencji w sposób podobny do aplikacji Home.
Obiekt PackageManager
zawiera zestaw metod query...()
, które zwracają wszystkie komponenty, które mogą odpowiadać na dany zamiar, oraz podobną serię metod resolve...()
, które określają najlepszy komponent do odpowiedzi na zamiar. Na przykład:
queryIntentActivities()
zwraca listę wszystkich działań, które mogą wykonać
intencję przekazaną jako argument, a queryIntentServices()
zwraca podobną listę usług.
Żadna z metod nie aktywuje komponentów. po prostu podają te,
mogą zareagować. W przypadku odbiorników w ramach transmisji queryBroadcastReceivers()
jest to podobna metoda.