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
oznacza jeden ekran w aplikacji. Możesz rozpocząć nowe wystąpienieActivity
, przekazującIntent
dostartActivity()
.Intent
opisuje aktywność, która ma zostać rozpoczęta i zawiera wszelkie niezbędne dane.Jeśli chcesz otrzymać wynik ćwiczenia po jego zakończeniu, Zadzwoń pod numer
startActivityForResult()
. Wynik Twojej aktywności jako osobny obiektIntent
w wywołaniu zwrotnymonActivityResult()
Twojej aktywności. Więcej informacji znajdziesz w przewodniku po ćwiczeniach. - Uruchamianie usługi
Service
to komponent, który wykonuje działania w tle bez użycia interfejsu użytkownika. W Androidzie 5.0 (poziom interfejsu API 21) i nowszych możesz uruchomić usługę dziękiJobScheduler
. Więcej informacji oJobScheduler
znajdziesz na stronieAPI-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. pobranie pliku), przekazującIntent
do:startService()
.Intent
opisuje usługę, która ma ją uruchomić i przekazuje wszelkie niezbędne dane.Jeśli usługa jest zaprojektowana z interfejsem klient-serwer, możesz ją powiązać z innym komponentem, przekazując obiekt
Intent
do obiektubindService()
. Więcej informacji znajdziesz w przewodniku po usługach. - Przesyłanie transmisji
Komunikat to wiadomość, którą może odebrać każda 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 typy intencji:
- Jasne intencje określają, który komponent której aplikacji ma spełnić intencję, przez podanie pełnego
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 pokazuje, w jaki sposób intencja jest wykorzystywana podczas rozpoczynania działania. Gdy
obiekt Intent
wprost określa nazwę konkretnego komponentu aktywności,
od razu uruchamia dany komponent.
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 pasuje kilka filtrów intencji,
wyświetla okno, 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 typ intencji, które komponent który 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 danej aktywności, możesz ją uruchomić. tylko z wyraźnym zamiarem.
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żywanie do uruchomienia usługi domyślnego zamiaru jest zagrożeniem dla bezpieczeństwa, 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 (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ć).
Intent
zawiera następujące informacje:
- Nazwa komponentu
- Nazwa komponentu, który ma zostać uruchomiony.
Nie jest to jednak wymagane, ale jest to kluczowa informacja, dzięki której explicit, co oznacza, że intencja powinna być dostarczana tylko do komponentu aplikacji. zdefiniowane przez nazwę komponentu. Bez nazwy komponentu intencja jest implicit, a system decyduje, który komponent powinien otrzymać intencję na podstawie innych informacji o intencji (takich jak działanie, dane i kategoria opisane poniżej). Jeśli chcesz utworzyć określony URL w swojej aplikacji, podaj nazwę komponentu.
Uwaga: gdy uruchamiasz
Service
, zawsze określaj 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
jestComponentName
, który możesz określić za pomocą kwalifikowana nazwa klasy komponentu docelowego, w tym nazwa pakietu aplikacji, np.com.example.ExampleActivity
Nazwę komponentu możesz ustawić za pomocą tych właściwości:setComponent()
,setClass()
,setClassName()
, lub za pomocąIntent
. - 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 to w dużym stopniu określa strukturę reszty intencji, a w szczególności zawarte w danych i dodatki.
Możesz określić własne działania do wykorzystania przez intencje w aplikacji (lub do wykorzystania przez inne aplikacji do wywoływania komponentów w aplikacji), ale zwykle określasz stałe działania. zdefiniowane przez klasę
Intent
lub inne klasy platformy. Oto kilka typowe czynności związane z rozpoczynaniem aktywności:ACTION_VIEW
- Wykonaj to działanie w zamiarze użycia:
startActivity()
, gdy masz informacje, które aktywność może być widoczna dla użytkownika, na przykład zdjęcie do wyświetlenia w aplikacji Galeria lub adres wyświetlić w aplikacji z mapami. ACTION_SEND
- Nazywa się to też intencją udostępniania. Należy jej używać w intencji
startActivity()
, gdy masz dane, które użytkownik może udostępniać za pomocą innej aplikacji, np. do 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 dokumentacji klasy
Intent
. 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:
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 do podejmowanych w związku z typu MIME. Typ dostarczanych danych jest zwykle określany przez działanie intencji. Dla: na przykład jeśli działaniem jestACTION_EDIT
, dane powinny zawierać parametr Identyfikator URI dokumentu do edycji.Podczas tworzenia intencji często warto określić typ danych (typ MIME) oprócz jego identyfikatora 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
setData()
. Aby ustawić tylko typ MIME, wywołajsetType()
. W razie potrzeby obie te wartości można ustawić bezpośrednio za pomocą funkcjisetDataAndType()
.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()
, aby ustawić typ URI i 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 popularnych 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ę znajdziesz w opisie zajęć
Intent
kategorii zainteresowań.Możesz określić kategorię za pomocą atrybutu
addCategory()
.
Te wymienione powyżej właściwości (nazwa komponentu, działanie, dane i kategoria) reprezentują określając cechy intencji. Odczytując te właściwości, system Android jest w stanie określić komponent aplikacji, który ma zostać uruchomiony. Intencja może jednak przenosić zawiera dodatkowe informacje, które nie mają wpływu jak jest on przekształcany w komponent aplikacji. Intencja może też dostarczać te informacje:
- Dodatki
- Pary klucz-wartość zawierające dodatkowe informacje wymagane do osiągnięcia
żądanego działania.
Niektóre działania używają określonych rodzajów identyfikatorów URI danych, tak samo niektóre działania wykorzystują też określone dodatki.
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 następnie wstawićBundle
wIntent
zputExtras()
.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
definiuje wiele stałychEXTRA_*
dla ujednoliconych typów danych. Jeśli musisz zadeklarować własne dodatkowe klucze (na potrzeby intencji, aplikacji), pamiętaj o umieszczeniu nazwy pakietu aplikacji jak w tym przykładzie:Kotlin
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Java
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 jawna intencja
Intencja jawna to taka, której używasz do uruchamiania konkretnego komponentu aplikacji, np.
do określonej aktywności lub usługi w aplikacji. Aby utworzyć intencję, zdefiniuj
nazwę komponentu Intent
.
inne właściwości intencji są opcjonalne.
Jeśli na przykład w aplikacji masz utworzoną usługę o nazwie DownloadService
,
przeznaczony do pobierania pliku z internetu, możesz rozpocząć go 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);
Intent(Context, Class)
Konstruktor dostarcza aplikację Context
oraz
do obiektu Class
. W związku z tym:
ta intencja wyraźnie rozpoczyna w aplikacji klasę DownloadService
.
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 chce użyć.
Jeśli na przykład masz treści, które użytkownicy mają udostępniać innym osobom,
utwórz intencję
z działaniem ACTION_SEND
i dodać dodatki 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.
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. }
Po wywołaniu funkcji startActivity()
system
sprawdza wszystkie zainstalowane aplikacje, aby określić, które z nich poradzą sobie z tego rodzaju intencjami (
intencja z działaniem ACTION_SEND
i zawierająca hasło „text/plain”
). Jeśli jest tylko jedna aplikacja, która może obsłużyć tę czynność, otwiera się ona natychmiast i otrzymuje odpowiednią intencję. Jeśli inne aplikacje nie są w stanie go obsłużyć, wychwytuje
ActivityNotFoundException
które występują. Jeśli kilka aktywności akceptuje intencję,
wyświetla okno podobne do pokazanego na Rysunku 2, dzięki czemu użytkownik może wybrać aplikację.
Więcej informacji o uruchamianiu innych aplikacji znajdziesz w przewodniku przesyłanianie użytkownika do innej aplikacji.
Wymuszenie wyboru aplikacji
Gdy więcej niż 1 aplikacja reaguje na intencje pośrednie, użytkownik może wybrać aplikację, której chce używać, i ustawić ją jako domyślną dla użytkownika, działania. 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 odpowiedzieć na intencję, a użytkownik może chcieć użyć innej
za każdym razem musisz 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). Na przykład gdy aplikacja wykonuje polecenie „udostępnij” używając działania ACTION_SEND
, użytkownicy mogą chcieć udostępnić treści za pomocą innej aplikacji w zależności od tego:
zgodnie z obecną sytuacją, należy więc zawsze korzystać z okna wyboru, tak jak na rys. 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.
W tym przykładzie wyświetla się okno z listą aplikacji, które odpowiadają na intencję przekazaną do metody createChooser()
i wykorzystują podany tekst jako
tytuł 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 uruchomić intencje nawigacji między komponentami w niej, 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()
Aby dowiedzieć się więcej o tym, jak wykryć taką sytuację i wprowadzić zmiany w aplikacji, przeczytaj post na blogu o zagnieżdżaniu na Androidzie Intencje w formacie Medium.
Sprawdzanie uruchamiania niebezpiecznych intencji
Aby sprawdzić, czy w aplikacji nie pojawiły się niebezpieczne intencje, wywołaj
detectUnsafeIntentLaunch()
podczas konfigurowania VmPolicy
, jak pokazano poniżej. Jeśli aplikacja wykryje naruszenie zasad trybu ścisłego, możesz zatrzymać jej działanie, aby chronić potencjalnie poufne 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()); }
Korzystaj z intencji bardziej odpowiedzialnie
Aby zminimalizować ryzyko niebezpiecznego uruchomienia intencji i naruszenia zasad StrictMode: przestrzegaj tych sprawdzonych metod.
Skopiuj tylko najważniejsze dodatki w intencjach i wykonaj niezbędne czyszczenie i weryfikację. Aplikacja może skopiować dodatkowe informacje z jednej intencji do innej, która służy do uruchamiania nowego komponentu. Dzieje się tak, gdy Twoja aplikacja wywołuje 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 inny zamiar (który otrzymuje kopię) uruchamia komponent, który nie został wyeksportowany, przed skopiowaniem dodatkowych informacji do zamiaru, który uruchamia komponent, należy je wyczyścić i sprawdzić.
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
.
Użyj PendingIntent
zamiast
intencja zagnieżdżona. Dzięki temu, gdy inna aplikacja ulepszy PendingIntent
swoich danych,
zawierający Intent
, inna aplikacja może uruchomić PendingIntent
za pomocą
tożsamości aplikacji. Ta konfiguracja umożliwia bezpieczne uruchomienie drugiej aplikacji
z dowolnym komponentem, w tym komponentem niewyeksportowanym.
Diagram na ilustracji 2 pokazuje, w jaki sposób system przekazuje kontrolę z klienta (klienta). do innej aplikacji (usługi) i z powrotem do aplikacji:
- Twoja aplikacja tworzy intencję, która wywołuje aktywność w innej aplikacji. W ramach tej intencji dodajesz obiekt
PendingIntent
jako dodatkowy. Ta intencja oczekująca wywołuje komponent w aplikacji; nie jest eksportowany. - Po otrzymaniu intencji aplikacji druga aplikacja wyodrębnia umieszczony w niej zagnieżdżony
PendingIntent
obiekt. - Druga aplikacja wywołuje metodę
send()
w obiekciePendingIntent
. - Po przekazaniu elementu sterującego do aplikacji system wywołuje oczekujące na podstawie 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 niejawne, 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 typ akceptowanych intencji na podstawie działania intencji
danych i kategorii. System dostarcza niejawną intencję do komponentu aplikacji tylko wtedy, gdy
intencja może przejść przez jeden z Twoich filtrów intencji.
Uwaga: intencja jawna jest zawsze dostarczana do miejsca docelowego. niezależnie od wszelkich intencji zadeklarowanych przez komponent.
Komponent aplikacji powinien zadeklarować osobne filtry dla każdego unikalnego zadania, które może wykonać.
Na przykład jedna aktywność w aplikacji galeria obrazów może mieć dwa filtry: jeden
aby wyświetlić obraz, a 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 element 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ć literałem wartości ciągu działania, a nie stałą klasy. <data>
- Deklaruje typ akceptowanych danych za pomocą co najmniej jednego atrybutu określającego różne
aspekty identyfikatora URI danych (
scheme
,host
,port
,path
) i typ MIME. <category>
- W atrybucie
name
deklaruje zaakceptowaną kategorię intencji. 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 deklaracja dotycząca aktywności z filtrem intencji, który otrzyma
intencja ACTION_SEND
, gdy typem danych jest 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 udostępni intencji . 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. Filtry intencji ograniczają komponentowi, aby mógł reagować tylko
określonych rodzajów niejawnych intencji, inna aplikacja może potencjalnie uruchomić komponent aplikacji.
za pomocą intencji, jeśli to deweloper określa nazwy komponentów.
Jeśli ważne jest, aby tylko Twoja aplikacja mogła uruchamiać jeden z komponentów,
nie deklaruj filtrów intencji w pliku manifestu. Zamiast tego skonfiguruj parametr
Atrybut exported
do "false"
dla tego komponentu.
Aby uniknąć przypadkowego uruchomienia innej aplikacji,
Service
, zawsze używaj jednoznacznej intencji, aby uruchomić własną usługę.
Uwaga:
W przypadku wszystkich działań musisz zadeklarować filtry intencji w pliku manifestu.
Filtry dla odbiorników transmisji mogą być jednak rejestrowane dynamicznie przez wywołanie funkcji registerReceiver()
. Potem możesz wyrejestrować odbiorcę w unregisterReceiver()
. Dzięki temu aplikacja może odbierać określone transmisje tylko przez określony czas, gdy jest uruchomiona.
Przykładowe filtry
Oto przykład, który pokazuje niektóre zachowania filtra intencji z pliku manifestu aplikacji do udostępniania treści 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>
.
Muszą one być ze sobą połączone, by aktywność była widoczna w Menu z aplikacjami.
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ęć panoramicznych, które można przetworzyć na Google
API panorama.
Dopasuj intencje do innych aplikacji filtry intencji
Jeśli inna aplikacja jest kierowana na Androida 13 (poziom interfejsu API 33) lub nowszego, może obsłużyć
do intencji aplikacji tylko wtedy, gdy intencja pasuje do działań i kategorii
<intent-filter>
w tej drugiej aplikacji. Jeśli system nie znajdzie
odpowiednik, rzuca
ActivityNotFoundException
Aplikacja wysyłająca musi obsłużyć tę sytuację.
Podobnie, jeśli 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 przypadkach dopasowywanie intencji nie jest egzekwowane:
- 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 intencji wysyłanych z systemu
„system UID” (uid=1000). Aplikacje systemowe to
system_server
oraz aplikacje, które ustawiają wartośćandroid:sharedUserId
naandroid.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łówny cel obiektu PendingIntent
jest zezwolenie na wyświetlanie zagranicznym wniosku
aby używać zawartego w nim elementu Intent
w taki sposób, jakby został on wykonany z Twojego
do własnego procesu aplikacji.
Główne przypadki użycia intencji oczekującej to:
- Oświadczenie, że chcesz wykonać działanie związane z powiadomieniem
(funkcja
NotificationManager
systemu Android wykonujeIntent
. - Deklaracja zamiaru wykonania, gdy użytkownik wykona działanie
Widżet aplikacji
(aplikacja ekranu głównego uruchamia
Intent
). - Deklaracja intencji do wykonania w określonym czasie w przyszłości (Android
AlarmManager
systemu 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 podczas tworzenia komponentu
PendingIntent
, wywołując odpowiednią metodę twórcy:
PendingIntent.getActivity()
zaIntent
, który rozpoczyna sięActivity
.PendingIntent.getService()
dlaIntent
, który rozpoczynaService
.PendingIntent.getBroadcast()
zaIntent
, który rozpoczyna sięBroadcastReceiver
.
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 używaniu oczekujących intencji znajdziesz w dokumentacji dotyczącej poszczególnych przypadków użycia, na przykład w przewodnikach po interfejsach API powiadomień i widżetów aplikacji.
Określ mutowalność
Jeśli Twoja aplikacja jest kierowana na Androida 12 lub nowszego, musisz podać
zmienność każdego obiektu PendingIntent
tworzonego przez aplikację. Zadeklarowanie, że
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.
Gdy tylko jest to możliwe, twórz stałe intencje oczekujące
W większości przypadków aplikacja powinna tworzyć stałe obiekty PendingIntent
, jak
w poniższym fragmencie kodu. Jeśli obiekt PendingIntent
jest stały,
to inne aplikacje nie mogą modyfikować intencji,
aby dostosować wynik wywołania funkcji
intencji.
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);
Jednak w niektórych przypadkach użycia wymagają zmiennych obiektów PendingIntent
:
- Obsługa odpowiedzi bezpośrednich w
powiadomienia.
bezpośrednia odpowiedź wymaga zmiany danych klipu w obiekcie PendingIntent
powiązanego z odpowiedzią. Zazwyczaj żądanie tej zmiany wymaga
FILL_IN_CLIP_DATA
jako flagę dlafillIn()
. . - 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 prośby o informacje o lokalizacji urządzenia przez telefon
requestLocationUpdates()
lub podobnych interfejsów API. Zmienny obiektPendingIntent
umożliwia systemowi dodawanie dodatkowych intencji, które reprezentują zdarzenia cyklu życia lokalizacji. Do tych zdarzeń należą: zmiana lokalizacji i dostępność usługodawcy. - Planuję alarmy za pomocą
AlarmManager
. Zmienny obiektPendingIntent
umożliwia systemowi dodawanie funkcjiEXTRA_ALARM_COUNT
. intencja użytkownika. Ten dodatkowy element pokazuje, ile razy powtarzający się alarm zostało wywołane. 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 to
za pomocą intencji jawnej i uzupełnić pole
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żywaj bezpośrednich intencji w ramach intencji oczekujących
Aby lepiej zdefiniować, jak inne aplikacje mogą korzystać z oczekujących intencji, zawsze otoczenie intencji oczekującej od intencji jawnej. Aby zastosować tę sprawdzoną metodę, wykonaj te czynności:
- Sprawdź, czy działanie, pakiet i pola komponentu podstawowej intencji są ustawione.
-
Użyj domeny
FLAG_IMMUTABLE
, dodano w Androidzie 6.0 (poziom interfejsu API 23) w celu utworzenia intencji oczekujących. Ta flaga uniemożliwia wypełnianie aplikacji, które otrzymują:PendingIntent
nieuzupełnione właściwości. JeśliminSdkVersion
w Twojej aplikacji to22
lub mniej, możesz zapewnić bezpieczeństwo i zgodność razem przy użyciu tego kodu:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
Rozwiązanie 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:
- Akcja.
- dane (identyfikator URI i typ danych).
- Category [Kategoria]:
W sekcjach poniżej opisujemy, jak intencje są dopasowywane do odpowiednich komponentów zgodnie z deklaracją filtra intencji w pliku manifestu aplikacji.
Test działania
Aby określić zaakceptowane działania intencji, filtr intencji może zadeklarować zero lub więcej.
<action>
zgodnie z tym przykładem:
<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 wyświetla żadnych działań, nie będzie żadnych wyników dla
więc wszystkie intencje kończą się niepowodzeniem. Jeśli jednak Intent
nie określa działania, test się powiedzie, o ile filtr zawiera co najmniej 1 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. Odwrotność nie jest konieczna – filtr intencji może
zadeklarować więcej kategorii niż określono w Intent
i
Intent
nadal ma podania. 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 intencji niejawnych przekazywanych do startActivity()
i startActivityForResult()
.
Jeśli chcesz, aby aktywność otrzymywała intencje niejawne, musi ona
uwzględnij kategorię dla elementu "android.intent.category.DEFAULT"
w filtrach intencji, jak
w poprzednim przykładzie
z <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>
Co <data>
może określać strukturę identyfikatora URI oraz typ danych (typ multimediów 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 schemat nie jest określony, host jest ignorowany.
- Jeśli nie podasz hosta, port będzie ignorowany.
- Jeśli nie określono zarówno schematu, jak i hosta, ścieżka jest ignorowana.
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. Reguły są następujące:
- Intencja, która nie zawiera ani identyfikatora URI, ani typu MIME, przechodzi test 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.
- Intencje zawierające zarówno identyfikator URI, jak i typ MIME (wyrażony w prosty sposób lub możliwy do wywnioskowania z identyfikatora URI) przechodzą test typu MIME tylko wtedy, gdy ten typ jest zgodny z typem wymienionym w filtrze. Przekazuje część URI testu
albo jeśli jego identyfikator URI pasuje do identyfikatora URI w filtrze lub ma
content:
lub identyfikator URIfile:
, a filtr nie określa identyfikatora URI. Innymi słowy, przyjmuje się, że komponent obsługuje danecontent:
ifile:
, jeśli jego filtr pokazuje 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, 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. Dla:
przykład: <data>
taki jak ten informuje Androida,
komponent może pobierać dane wideo z sieci w celu wykonania działania:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
Dopasowywanie intencji
Intencje są dopasowywane do filtrów intencji nie tylko w celu wykrycia celu
do aktywacji, ale też aby dowiedzieć się więcej o zestawie
komponentów. Na przykład aplikacja Home wypełnia Menu z aplikacjami
znajdując wszystkie działania z filtrami intencji, które określają
ACTION_MAIN
działanie i
Kategoria CATEGORY_LAUNCHER
.
Dopasowanie jest udane tylko wtedy, gdy działania i kategorie w intencji odpowiadają danym intencji.
zgodnie z opisem w dokumentacji funkcji IntentFilter
zajęcia.
Aplikacja może korzystać z dopasowywania intencji w sposób podobny do działania 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. Przykład:
queryIntentActivities()
zwraca listę wszystkich działań, które mogą wykonać
intencja przekazana jako argument, a queryIntentServices()
zwraca podobną listę usług.
Żadna z metod nie aktywuje komponentów. po prostu podają te,
mogą zareagować. Istnieje podobna metoda,
queryBroadcastReceivers()
dla odbiorników.