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 na temat konfiguracji 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. 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 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 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 ich używać. Powiązane informacje: Interakcje z innymi aplikacjami oraz Udostępnianie treści.
Typy intencji
Istnieją 2 typy intencji:
- Intencje jawne określają, który komponent danej aplikacji spełni intencję, poprzez określenie pełnego parametru
ComponentName
. Za zwykle używają jednoznacznej intencji, aby uruchomić komponent masz własną aplikację, 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ą działanie ogólne. umożliwia jego obsługę komponentowi z innej aplikacji. 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ż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
zwróci wyjątek, jeśli wywołasz funkcję bindService()
z intencją niejawną.
Budowanie zamiaru
Obiekt Intent
zawiera informacje używane przez system Android
w celu określenia, który komponent należy uruchomić (np. dokładna nazwa komponentu lub komponent).
kategoria, która powinna otrzymać intencję), oraz informacje używane przez komponent odbiorcy
na potrzeby prawidłowego wykonania czynności (np. działania i danych, na które należy podjąć działanie).
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 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
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 informacji znajdziesz w dokumentacji zajęć
Intent
. stałe, które definiują działania ogólne. Zdefiniowano inne działania w innym miejscu platformy Androida, na przykład wSettings
w przypadku działań. które otwierają określone ekrany w systemowej aplikacji Ustawienia.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.Gdy tworzysz intencję, 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ć 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 identyfikator URI, jak i typ MIME, nie dzwoń do:
setData()
isetType()
, bo każdy z nich anuluje wartość drugiego. 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ę. Można użyć dowolnej liczby opisów kategorii,
są umieszczane w intencji, 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 reklam.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.
Możesz dodawać dodatkowe dane za pomocą różnych metod
putExtra()
, każdy z nich akceptuje 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
określa wiele stałychEXTRA_*
dla ustandaryzowanych 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 opisie metody
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 Przewodnik po usługach.
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ż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 dzwonisz
startActivity()
z tym zamiarem, użytkownik może
wybierz aplikację, za pomocą której chcesz 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 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 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 na temat wprowadzania innych aplikacji znajdziesz w przewodniku o wysyłaniu użytkownika do innej aplikacji.
Wymuszanie 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 jest
wybór aplikacji, która ma zostać wykonana w ramach danego działania (nie może on wybrać aplikacji domyślnej
działanie). 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
jeśli aplikacja wykryje naruszenie zasad StrictMode, możesz zatrzymać wykonywanie aplikacji,
ochrony potencjalnie poufnych informacji.
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 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
.
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:
- Aplikacja tworzy intencję, która wywołuje działanie w innej aplikacji. W ciągu
dla tej intencji, dodaj obiekt
PendingIntent
jako dodatek. 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 definiowany przez element <intent-filter>
w pliku manifestu aplikacji zagnieżdżonym w odpowiednim komponencie aplikacji (takim jak
jako <activity>
).
W każdym komponencie aplikacji, który zawiera element <intent-filter>
,
jawnie ustaw wartość dla
android:exported
Ten atrybut wskazuje, czy komponent 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 obejmujący więcej niż jedno wystąpienie
<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 . Komponent może jednak mieć wiele filtrów intencji, więc intencja, która takie działanie jeśli jeden z filtrów komponentu może nie przejść przez inny filtr. 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 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
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 ta aktywność jest należy umieścić w systemowym Menu z aplikacjami. 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ą dołączyć do tej aktywności po przejściu do niej z MainActivity
,
mogą też wpisać ShareActivity
bezpośrednio z innej aplikacji, która generuje niejawnie
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ęć 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ługiwać
ten wyjątek.
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>
. To zachowanie
występuje niezależnie od wersji docelowej pakietu SDK aplikacji wysyłającej.
W tych przypadkach dopasowywanie intencji nie jest egzekwowane:
- 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 intencji wysyłanych z systemu
„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łó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()
zaIntent
, który rozpoczyna sięService
.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 pobiera bieżącą aplikację Context
,
Intent
, które chcesz zapakować, oraz co najmniej 1 flagę określającą
sposób jej użycia (np. czy intencja może być używana 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 przewodników po interfejsie API App Widgets.
Określ zmienność
Jeśli Twoja aplikacja jest kierowana na Androida 12 lub nowszego, musisz podać
zmienność każdego obiektu PendingIntent
tworzonego przez aplikację. 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.
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 skorzystać ze sprawdzonych metod, wykonaj te czynności:
- Sprawdź, czy działanie, pakiet i pola komponentu intencji podstawowej ustawienia.
-
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 przechodzi test, dopóki filtr
zawiera co najmniej jedno działanie.
Test 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. Zamiar bez kategorii
zawsze zalicza 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 stanowi osobny identyfikator
atrybut: 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 zawierają symbol wieloznaczny (*), co 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, przekazuje testu tylko wtedy, gdy filtr nie określa żadnych identyfikatorów URI ani typów MIME.
- Intencja zawierająca identyfikator URI, ale bez typu MIME (ani jawna, ani niewywnioskowana na podstawie URI) przechodzi test tylko wtedy, gdy jego identyfikator URI pasuje do formatu URI filtra. a filtr także nie określa typu MIME.
- Intencja, która zawiera typ MIME, ale nie identyfikator URI, kończy test. tylko wtedy, gdy filtr zawiera ten sam typ MIME i nie określa formatu identyfikatora 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. 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 typu danych, ale nie identyfikatora URI, są najprawdopodobniej najczęstsze, są dostarczane 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 urządzenia. 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.
PackageManager
zawiera zbiór query...()
Metody, które zwracają wszystkie komponenty, które mogą zaakceptować konkretną intencję
podobnej serii resolve...()
metod, które określają najlepszą
w odpowiedzi na intencję. 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.