Un Intent
est un objet de messagerie que vous pouvez utiliser pour demander une action
à partir d'un autre composant d'application.
Bien que les intents facilitent la communication entre les composants de plusieurs manières, il existe trois cas d'utilisation fondamentaux :
- Démarrer une activité
Un
Activity
représente un seul écran dans une application. Vous pouvez démarrer une nouvelle une instance deActivity
en transmettant unIntent
; àstartActivity()
.Intent
décrit l'activité à démarrer et contient toutes les données nécessaires.Si vous souhaitez recevoir un résultat de l'activité une fois celle-ci terminée, appeler
startActivityForResult()
. Votre activité reçoit le résultat en tant qu'objetIntent
distinct dans le rappelonActivityResult()
de votre activité. Pour en savoir plus, consultez le guide Activités. - Démarrer un service
Un
Service
est un composant qui effectue des opérations en arrière-plan. sans interface utilisateur. Avec Android 5.0 (niveau d'API 21) ou version ultérieure, vous pouvez démarrer un service avecJobScheduler
. Pour en savoir plus, concernantJobScheduler
, consultez sesAPI-reference documentation
Pour les versions antérieures à Android 5.0 (niveau d'API 21), vous pouvez démarrer un service à l'aide des méthodes de la classe
Service
. Vous pouvez démarrer un service pour effectuer une opération unique (comme le téléchargement d'un fichier) en transmettant unIntent
àstartService()
.Intent
décrit le service à démarrer et transporte toutes les données nécessaires.Si le service est conçu avec une interface client-serveur, vous pouvez lier au service à partir d'un autre composant en transmettant un
Intent
àbindService()
. Pour en savoir plus, consultez le guide Services. - Diffuser une diffusion
Une annonce est un message que n'importe quelle application peut recevoir. Le système propose différentes diffuse des annonces pour des événements système, par exemple lorsque le système démarre ou que l'appareil commence à se recharger. Vous pouvez diffuser une diffusion à d'autres applications en transmettant un
Intent
verssendBroadcast()
ousendOrderedBroadcast()
Le reste de cette page explique le fonctionnement des intents et leur utilisation. Pour en savoir plus, consultez Interaction avec d'autres applications et Partage de contenu.
Types d'intents
Il existe deux types d'intents:
- Les intents explicites spécifient le composant de quelle application répondra à l'intent, en spécifiant un
ComponentName
complet. Vous allez utilisent généralement un intent explicite pour démarrer un composant votre propre application, car vous connaissez le nom de classe de l'activité ou du service que vous souhaitez démarrer. Pour Par exemple, vous pouvez démarrer une nouvelle activité dans votre application en réponse à une action de l'utilisateur, ou bien démarrer un service pour télécharger un fichier en arrière-plan. - Les intents implicites ne nomment pas un composant spécifique, mais déclarent une action générale ce qui permet à un composant d'une autre application de le gérer. Par exemple, si vous souhaitez afficher un emplacement sur une carte, vous pouvez utiliser un intent implicite pour demander qu'un autre d'afficher un lieu spécifique sur une carte.
La figure 1 montre comment un intent est utilisé lors du démarrage d'une activité. Lorsque
L'objet Intent
nomme explicitement un composant d'activité spécifique, le système
démarre immédiatement
ce composant.
Lorsque vous utilisez un intent implicite, le système Android trouve le composant approprié pour démarrer
en comparant le contenu de l'intent aux filtres d'intent déclarés dans le fichier manifeste d'autres applications sur le
appareil. Si l'intent correspond à un filtre d'intent, le système démarre ce composant et le diffuse
l'objet Intent
. Si plusieurs filtres d'intent sont compatibles, le système affiche une boîte de dialogue permettant à l'utilisateur de choisir l'application à utiliser.
Un filtre d'intent est une expression dans le fichier manifeste d'une application qui spécifie le type d'intents que le composant souhaite recevoir. Par exemple, en déclarant un filtre d'intent pour une activité, vous permettez à d'autres applications de démarrer directement votre activité avec un certain type d’intention. De même, si vous ne déclarez pas de filtres d'intent pour une activité, celle-ci peut être lancée qu'avec un intent explicite.
Attention:Pour vous assurer que votre application est sécurisée, veillez toujours
utilisent un nom
lors du démarrage d'une Service
et ne
déclarer des filtres d'intent pour vos services. L'utilisation d'un intent implicite pour démarrer un service
car vous ne pouvez pas savoir
quel service répondra à l'intent,
et l'utilisateur ne peut pas voir
quel service démarre. À partir d'Android 5.0 (niveau d'API 21), le système
génère une exception si vous appelez bindService()
.
avec un intent implicite.
Créer un intent
Un objet Intent
contient des informations utilisées par le système Android.
pour déterminer quel composant démarrer (comme le nom ou le nom exact du composant
la catégorie qui doit recevoir l'intent), ainsi que les informations utilisées par le composant destinataire
afin d'effectuer correctement l'action (par exemple, l'action à effectuer et les données sur lesquelles agir).
Les informations principales contenues dans un Intent
sont les suivantes:
- Nom du composant
- Nom du composant à démarrer.
Cette étape est facultative, mais c'est l'information essentielle qui fait qu'un intent explicite, ce qui signifie que l'intent ne doit être diffusé qu'au composant de l'application. défini par le nom du composant. Sans nom de composant, l'intent est implicite. le système décide quel composant doit recevoir l'intent en fonction des autres informations sur l'intent (telle que l'action, les données et la catégorie décrites ci-dessous). Si vous devez démarrer un composant spécifique dans votre application, vous devez spécifier son nom.
Remarque:Lorsque vous démarrez une
Service
, indiquez toujours le nom du composant. Sinon, vous ne pouvez pas savoir avec certitude quel service répond à l'intent, et l'utilisateur ne peut pas voir quel service démarre.Ce champ de
Intent
est unComponentName
, que vous pouvez spécifier à l'aide d'un objet nom de classe qualifié du composant cible, y compris le nom de package de l'application, par exemple,com.example.ExampleActivity
Vous pouvez définir le nom du composant avecsetComponent()
,setClass()
,setClassName()
, ou à l'aide de l'Intent
. - Action
- Chaîne spécifiant l'action générique à effectuer (par exemple, Afficher ou Sélectionner).
Dans le cas d'un intent de diffusion, il s'agit de l'action qui a eu lieu et qui est signalée. L'action détermine en grande partie la structure du reste de l'intent, en particulier les informations contenues dans les données et les extras.
Vous pouvez spécifier vos propres actions à utiliser par les intents dans votre application (ou par d'autres applications pour appeler des composants dans votre application), mais vous spécifiez généralement des constantes d'action défini par la classe
Intent
ou d'autres classes de framework. Voici quelques exemples actions courantes pour démarrer une activité:ACTION_VIEW
- Utilisez cette action dans un intent avec
startActivity()
lorsque vous disposez d'informations qu'une activité peut afficher à l'utilisateur, comme une photo à afficher dans une application de galerie ou une adresse à afficher dans une application de carte. ACTION_SEND
- Également appelé intent de partage, vous devez l'utiliser dans un intent avec
startActivity()
lorsque vous disposez de données que l'utilisateur peut partager des contenus via une autre application, telle qu'une application de messagerie ou de partage sur les réseaux sociaux.
Pour en savoir plus, consultez la documentation de référence de la classe
Intent
. qui définissent des actions génériques. D'autres actions sont définies ailleurs dans le framework Android, par exemple dansSettings
pour les actions qui ouvrent des écrans spécifiques dans l'application Paramètres du système.Vous pouvez spécifier l'action d'un intent avec
setAction()
ou avec un constructeurIntent
.Si vous définissez vos propres actions, veillez à inclure le nom du package de votre application comme préfixe, comme indiqué dans l'exemple suivant :
Kotlin
const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"
Java
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
- Données
- L'URI (un objet
Uri
) qui référence les données faire l'objet d'une action et/ou le type MIME de ces données. Le type de données fournies est généralement dicté par l'action de l'intent. Pour Par exemple, si l'action estACTION_EDIT
, les données doivent contenir le URI du document à modifier.Lors de la création d'un intent, il est souvent important de spécifier le type de données (son type MIME) en plus de son URI. Par exemple, une activité capable d'afficher des images ne pourra probablement pas pour lire un fichier audio, même si les formats d'URI peuvent être similaires. Spécifier le type MIME de vos données aide le système Android à trouver le meilleur composant pour recevoir votre intent. Cependant, le type MIME peut parfois être déduit de l'URI, en particulier lorsque les données sont URI
content:
. Un URIcontent:
indique que les données se trouvent sur l'appareil. et contrôlé par uneContentProvider
, qui permet au système de voir le type MIME des données.Pour définir uniquement l'URI de données, appelez
setData()
. Pour définir uniquement le type MIME, appelezsetType()
. Si nécessaire, vous vous pouvez définir les deux explicitement avecsetDataAndType()
.Attention:Si vous souhaitez définir à la fois l'URI et le type MIME, n'appelez pas
setData()
etsetType()
, car chacune d'elles invalide la valeur de l'autre. Toujours utilisersetDataAndType()
pour définir les deux l'URI et le type MIME. - Catégorie
- Chaîne contenant des informations supplémentaires sur le type de composant
qui doit gérer l'intent. Vous pouvez placer un nombre illimité de descriptions de catégories dans un intent, mais la plupart des intents n'en ont pas besoin.
Voici quelques catégories courantes :
CATEGORY_BROWSABLE
- L'activité cible peut être lancée par un navigateur Web pour afficher les données référencées par un lien, comme une image ou un message d'e-mail.
CATEGORY_LAUNCHER
- L'activité est l'activité initiale d'une tâche. Elle est répertoriée dans le lanceur d'applications du système.
Consultez la description de la classe
Intent
pour obtenir la liste complète des catégories.Vous pouvez spécifier une catégorie avec
addCategory()
.
Les propriétés répertoriées ci-dessus (nom du composant, action, données et catégorie) représentent définir les caractéristiques d'un intent. En lisant ces propriétés, le système Android peut déterminer quel composant d'application il doit démarrer. Cependant, un intent peut transmettre d'autres informations n'ayant aucune incidence sur comment il est résolu en composant d'application. Un intent peut également fournir les informations suivantes:
- Extras
- Paires clé-valeur contenant les informations supplémentaires requises pour effectuer
l'action demandée.
Tout comme certaines actions utilisent certains types d'URI de données, d'autres utilisent également des extras particuliers.
Vous pouvez ajouter des données supplémentaires à l'aide de différentes méthodes
putExtra()
. chacun acceptant deux paramètres: le nom de la clé et la valeur. Vous pouvez également créer un objetBundle
avec toutes les données supplémentaires, puis insérerBundle
dansIntent
parputExtras()
.Par exemple, lors de la création d'un intent pour envoyer un e-mail avec
ACTION_SEND
, vous pouvez spécifier le destinataire to à l'aide du paramètreEXTRA_EMAIL
et spécifiez l'objet avec le toucheEXTRA_SUBJECT
.La classe
Intent
spécifie de nombreuses constantesEXTRA_*
. pour les types de données standardisés. Si vous devez déclarer vos propres clés supplémentaires (pour les intents qui reçu par votre application), veillez à inclure le nom du package de votre application en tant que préfixe, comme illustré dans l'exemple suivant:Kotlin
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Java
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Attention : N'utilisez pas de données
Parcelable
niSerializable
lorsque vous envoyez un intent que vous attendez d'une autre application. Si une application tente d'accéder aux données d'un objetBundle
, mais ne tente pas à la classe fragmentée ou sérialisée, le système génère uneRuntimeException
- Indicateurs
- Les options sont définies dans la classe
Intent
et servent de métadonnées pour l'élément l'intention. Les indicateurs peuvent indiquer au système Android comment lancer une activité (par exemple, tâche l'activité doit appartenir et comment les traiter après leur lancement (par exemple, s'ils figurent dans la liste des applications récentes activités).Pour en savoir plus, consultez la méthode
setFlags()
.
Exemple d'intent explicite
Un intent explicite est un intent que vous utilisez pour lancer un composant d'application spécifique,
une activité ou un service particulier dans votre application. Pour créer un intent explicite, définissez
le nom de composant de l'objet Intent
(all
les autres propriétés d'intent sont facultatives.
Par exemple, si vous avez créé un service nommé DownloadService
dans votre application,
conçu pour télécharger un fichier à partir du Web, vous pouvez le démarrer avec le code suivant:
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)
fournit l'application Context
et le
un objet Class
. Par conséquent, cet intent démarre explicitement la classe DownloadService
dans l'application.
Pour en savoir plus sur la création et le démarrage d'un service, consultez la Services.
Exemple d'intent implicite
Un intent implicite spécifie une action qui peut appeler n'importe quelle application sur l'appareil pour effectuer l'action. L'utilisation d'un intent implicite est utile lorsque votre application ne peut pas effectuer l'action d'autres applications, mais vous souhaitez que l'utilisateur choisisse l'application à utiliser.
Par exemple, si vous souhaitez
que l'utilisateur partage du contenu,
créer un intent
avec l'action ACTION_SEND
et ajouter des éléments supplémentaires
indiquant le contenu à partager. Lorsque vous appelez
startActivity()
avec cet intent, l'utilisateur peut
choisissez une application
par laquelle partager le contenu.
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. }
Lorsque startActivity()
est appelé, le système
examine toutes les applications installées pour déterminer celles qui peuvent gérer ce type d'intent (une
intent avec l'action ACTION_SEND
et qui contient "text/plain"
données). Si une seule application est compatible, elle s'ouvre immédiatement et reçoit le paramètre
l'intention. Si aucune autre application ne peut le gérer, votre application peut intercepter l'exception ActivityNotFoundException
qui se produit. Si plusieurs activités acceptent l'intent, le système affiche une boîte de dialogue telle que celle illustrée dans la figure 2, afin que l'utilisateur puisse choisir l'application à utiliser.
Vous trouverez également dans ce guide des informations supplémentaires sur le lancement d'autres applications. d'envoyer l'utilisateur une autre application.
Forcer un sélecteur d'application
Lorsque plusieurs applications répondent à votre intent implicite, l'utilisateur peut sélectionner l'application à utiliser et en faire le choix par défaut pour action. La possibilité de sélectionner une valeur par défaut est utile lorsque l'utilisateur effectue une action souhaite probablement utiliser la même application à chaque fois, par exemple à l'ouverture d'une page Web (les utilisateurs préfèrent souvent un seul navigateur Web).
Toutefois, si plusieurs applications peuvent répondre à l'intent et que l'utilisateur peut souhaiter utiliser un autre
application, vous devez afficher explicitement une boîte de dialogue de sélection. La boîte de dialogue du sélecteur demande au
l'utilisateur de sélectionner l'application à utiliser pour l'action (l'utilisateur ne peut pas sélectionner une application par défaut pour
l'action). Par exemple, lorsque votre application effectue l'action "Partager" avec l'action ACTION_SEND
, les utilisateurs voudront peut-être partager du contenu à l'aide d'une autre application en fonction
en fonction de sa situation actuelle. Vous devez donc toujours utiliser la boîte de dialogue du sélecteur, comme illustré dans la figure 2.
Pour afficher le sélecteur, créez un Intent
à l'aide de createChooser()
et transmettez-le à startActivity()
, comme illustré dans l'exemple suivant.
Cet exemple affiche une boîte de dialogue contenant la liste des applications qui répondent à l'intent transmis à la méthode createChooser()
et utilise le texte fourni comme titre de la boîte de dialogue.
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); }
Détecter les lancements d'intents non sécurisés
Votre application peut lancer des intents pour naviguer entre ses composants, ou pour effectuer une action pour le compte d'une autre application. Pour améliorer la sécurité de la plate-forme, Android 12 (niveau d'API 31) ou version ultérieure fournit une fonctionnalité de débogage qui vous avertit si votre application effectue un lancement non sécurisé d'un intent. Par exemple, votre application peut effectuer un lancement non sécurisé d'un intent imbriqué. Cet intent est transmis en tant qu'extra dans un autre intent.
Si votre appli effectue les deux actions suivantes, le système détecte un danger le lancement d'un intent et le non-respect du StrictMode se produit:
- Votre application dissocie un intent imbriqué des extras d'un intent livré.
- Votre application lance immédiatement une application
à l'aide de cet intent imbriqué.
par exemple en transmettant l'intent
startActivity()
,startService()
, oubindService()
Pour savoir comment identifier cette situation et apporter des modifications à votre application, lisez l'article de blog sur l'imbrication d'appareils Android Intents sur Medium.
Rechercher les lancements d'intent non sécurisés
Pour vérifier les lancements d'intent dangereux dans votre application, appelez detectUnsafeIntentLaunch()
lorsque vous configurez votre VmPolicy
, comme indiqué dans l'extrait de code suivant. Si
votre application détecte un cas de non-respect du StrictMode, vous pouvez arrêter son exécution pour
protéger les informations
potentiellement sensibles.
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()); }
Utiliser les intentions de manière plus responsable
Pour réduire le risque de lancement d'un intent non sécurisé et de non-respect du StrictMode, suivez ces bonnes pratiques.
Copiez uniquement les extras essentiels dans les intents et effectuez tous les opérations nécessaires.
l'assainissement et la validation. Votre application peut copier les extras
d'un intent vers
et un autre intent pour lancer un nouveau composant. Cela se produit lorsque votre
appels d'application
putExtras(Intent)
ou
putExtras(Bundle)
Si votre application effectue l'une de ces opérations, ne copiez que les extras
du composant destinataire. Si l'autre intent (qui reçoit la copie)
lance un composant qui n'est pas
exporté, désinfecté
Validez les extras avant de les copier dans l'intent qui lance le
.
N'exportez pas inutilement les composants de votre application. Par exemple, si vous
si vous souhaitez lancer un composant d'application à l'aide d'un intent imbriqué interne, définissez ce
l'attribut android:exported
du composant sur false
.
Utilisez un PendingIntent
au lieu d'un
un intent imbriqué. De cette façon, lorsqu'une autre application dépare le PendingIntent
de son
contenant Intent
, l'autre application peut lancer PendingIntent
à l'aide de
l'identité de votre application. Cette configuration permet à l'autre application de se lancer en toute sécurité
n'importe quel composant de votre application, y compris un composant non exporté.
Le diagramme de la figure 2 montre comment le système transmet le contrôle de votre application (client) à une autre application (service), puis de nouveau à votre application :
- Votre application crée un intent qui appelle une activité dans une autre application. Dans
cet intent, vous ajoutez un objet
PendingIntent
en tant qu'extra. Cet intent en attente appelle un composant de votre application. Ce composant n'est pas exporté. - Après avoir reçu l'intent de votre application, l'autre application extrait l'élément
PendingIntent
. - L'autre application appelle la méthode
send()
sur l'objetPendingIntent
. - Après avoir redonné le contrôle à votre application, le système appelle l'intent en attente à l'aide du contexte de votre application.
Figure 2. Schéma de la communication inter-application lors de l'utilisation d'un intent en attente imbriqué.
Recevoir un intent implicite
Pour annoncer les intents implicites que votre application peut recevoir, déclarez un ou plusieurs filtres d'intent pour
chacun des composants de votre application avec un élément <intent-filter>
dans le fichier manifeste.
Chaque filtre d'intent spécifie le type d'intents qu'il accepte en fonction de l'action de l'intent.
des données et des catégories. Le système ne transmet un intent implicite à votre composant d'application que si l'intent peut passer par l'un de vos filtres d'intent.
Remarque:Un intent explicite est toujours envoyé à sa cible, quels que soient les filtres d'intent déclarés par le composant.
Un composant d'application doit déclarer des filtres distincts pour chaque tâche unique qu'il peut effectuer.
Par exemple, une activité dans une application de galerie d'images peut comporter deux filtres: un filtre
pour afficher une image, et un autre filtre pour la modifier. Lorsque l'activité commence,
Il inspecte Intent
et détermine son comportement en fonction des informations
dans Intent
(par exemple, pour afficher ou non les commandes de l'éditeur).
Chaque filtre d'intent est défini par un élément <intent-filter>
dans le fichier manifeste de l'application, imbriqué dans le composant correspondant (par exemple,
en tant que <activity>
).
Dans chaque composant d'application qui inclut un élément <intent-filter>
, définissez explicitement une valeur pour android:exported
.
Cet attribut indique si d'autres applications peuvent accéder au composant d'application. Dans certains
telles que les activités dont les filtres d'intent incluent le
LAUNCHER
il est utile de définir cet attribut sur true
. Sinon,
il est plus sûr de définir cet attribut sur false
.
Avertissement:Si une activité, un service ou une annonce
récepteur de votre application utilise des filtres d'intent et ne définit pas explicitement la valeur
pour android:exported
, votre appli ne peut pas être installée sur un appareil
fonctionne sous Android 12 ou version ultérieure.
Dans <intent-filter>
,
vous pouvez spécifier le type d'intents à accepter en utilisant un ou plusieurs
de ces trois éléments:
<action>
- Déclare l'action d'intent acceptée, dans l'attribut
name
. La valeur doit être la valeur littérale de chaîne d'une action, et non la constante de classe. <data>
- Déclare le type de données accepté à l'aide d'un ou de plusieurs attributs spécifiant différents
aspects de l'URI de données (
scheme
,host
,port
,path
) et le type MIME. <category>
- Déclare la catégorie d'intent acceptée, dans l'attribut
name
. La valeur doit correspondre à la valeur de chaîne littérale d'une action, et non à la constante de classe.Remarque:Pour recevoir des intents implicites, vous devez doit inclure le
CATEGORY_DEFAULT
dans le filtre d'intent. Les méthodesstartActivity()
etstartActivityForResult()
traiter tous les intents comme s'il avait déclaré la catégorieCATEGORY_DEFAULT
. Si vous ne déclarez pas cette catégorie dans votre filtre d'intent, aucun intent implicite ne pourra renvoyer votre activité.
Par exemple, voici une déclaration d'activité avec un filtre d'intent pour recevoir un intent ACTION_SEND
lorsque le type de données est du texte :
<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>
Vous pouvez créer un filtre qui inclut plusieurs instances de <action>
, <data>
ou <category>
.
Si c'est le cas, vous devez vous assurer que le composant peut gérer tout
une combinaison de ces éléments de filtre.
Lorsque vous souhaitez gérer plusieurs types d'intents, mais seulement dans des combinaisons spécifiques d'action, de données et de catégorie, vous devez créer plusieurs filtres d'intent.
Un intent implicite est testé par rapport à un filtre en comparant l'intent à chacun des trois éléments. Pour être diffusé au composant, l'intent doit réussir les trois tests. S'il ne parvient pas à établir une correspondance, même l'un d'entre eux, le système Android ne transmettra pas l'intent à . Toutefois, comme un composant peut avoir plusieurs filtres d'intent, un intent ne pas passer par l’un des filtres d’un composant pourrait le faire sur un autre filtre. Vous trouverez plus d'informations sur la manière dont le système résout les intents dans la section ci-dessous sur la résolution d'intent.
Attention : L'utilisation d'un filtre d'intent n'est pas un moyen sécurisé d'empêcher le démarrage d'autres applications
vos composants. Bien que les filtres d'intent limitent l'accès d'un composant
certains types d'intents implicites, une autre application peut potentiellement démarrer le composant d'application
à l'aide d'un intent explicite si le développeur détermine le nom de vos composants.
Si vous souhaitez que seule votre propre application puisse démarrer l'un de vos composants, ne déclarez pas de filtres d'intent dans votre fichier manifeste. Définissez plutôt le paramètre
Attribut exported
sur "false"
pour ce composant.
De même, pour éviter d'exécuter par inadvertance une autre
Service
: utilisez toujours un intent explicite pour démarrer votre propre service.
Remarque:
Pour toutes les activités, vous devez déclarer vos filtres d'intent dans le fichier manifeste.
Toutefois, les filtres pour les broadcast receivers peuvent être enregistrés de manière dynamique en appelant
registerReceiver()
Vous pouvez ensuite annuler l'enregistrement du broadcast receiver avec unregisterReceiver()
. Cela permet à votre application
pour écouter des annonces spécifiques pendant une période donnée pendant que votre application
est en cours d'exécution.
Exemples de filtres
Pour illustrer certains comportements des filtres d'intent, voici un exemple à partir du fichier manifeste d'une application de partage sur les réseaux sociaux:
<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>
La première activité, MainActivity
, est le point d'entrée principal de l'application, c'est-à-dire l'activité qui s'ouvre lorsque l'utilisateur lance l'application pour la première fois avec l'icône du lanceur :
- L'action
ACTION_MAIN
indique qu'il s'agit du point d'entrée principal et ne nécessite aucune donnée d'intent. - La catégorie
CATEGORY_LAUNCHER
indique que cette activité doit être placée dans le lanceur d'applications du système. Si l'élément<activity>
ne spécifie pas d'icône avecicon
, le système utilise l'icône de<application>
.
Ces deux éléments doivent être associés pour que l'activité apparaisse dans le lanceur d'applications.
La deuxième activité, ShareActivity
, vise à faciliter le partage de texte et de contenus multimédias.
de votre contenu. Bien que les utilisateurs puissent entrer dans cette activité en y accédant depuis MainActivity
,
ils peuvent également saisir ShareActivity
directement à partir d'une autre application qui émet un élément implicite
l'intent correspondant à l'un des deux filtres d'intent.
Remarque:Le type MIME,
application/vnd.google.panorama360+jpg
, est un type de données spécial qui spécifie
des photos panoramiques, que vous pouvez gérer avec le
Panorama.
Associer des intents aux filtres d'intent d'autres applications
Si une autre application cible Android 13 (niveau d'API 33) ou une version ultérieure, elle peut gérer vos
l'intent de votre application uniquement s'il correspond aux actions et aux catégories d'une
<intent-filter>
de cette autre application. Si le système ne trouve pas de
génère une correspondance
ActivityNotFoundException
L'application d'envoi doit gérer
cette exception.
De même, si vous mettez à jour votre application afin qu'elle cible Android 13
tous les intents provenant d'applications externes sont transmis à
composant exporté de votre application uniquement si cet intent correspond aux actions et
catégories d'un élément <intent-filter>
déclaré par votre application. Ce comportement
quelle que soit la version du SDK cible de l'application émettrice.
Dans les cas suivants, la mise en correspondance des intents n'est pas appliquée :
- Intents envoyés à des composants qui ne déclarent aucun filtre d'intent.
- Intents provenant de la même application
- Intents provenant du système c'est-à-dire que les intents sont envoyés
"UID du système" (uid=1000). Les applications système incluent
system_server
et les applications qui définissentandroid:sharedUserId
àandroid.uid.system
. - Intents provenant de la racine.
En savoir plus sur la mise en correspondance des intents
Utiliser un intent en attente
Un objet PendingIntent
est un wrapper autour d'un objet Intent
. Objectif principal d'un PendingIntent
est d'accorder une autorisation à une application
d'utiliser le Intent
contenu comme s'il avait été exécuté à partir de votre
propre processus de votre application.
Voici les principaux cas d'utilisation d'un intent en attente :
- Déclarer un intent à exécuter lorsque l'utilisateur effectue une action via votre notification
(l'
NotificationManager
du système Android exécuteIntent
). - Déclarer un intent à exécuter lorsque l'utilisateur effectue une action avec votre
Widget d'application
(l'application de l'écran d'accueil exécute
Intent
). - Déclarer un intent à exécuter à un moment précis
AlarmManager
du système exécuteIntent
).
Tout comme chaque objet Intent
est conçu pour être géré par une personne spécifique
le type de composant d'application (Activity
, Service
ou
BroadcastReceiver
), tout comme un PendingIntent
doit être
créé avec la même considération. Lorsque vous utilisez un intent en attente, votre application
exécuter l'intent avec un appel tel que startActivity()
. À la place, vous devez déclarer le type de composant souhaité lorsque vous créez le
PendingIntent
en appelant la méthode de créateur correspondante:
PendingIntent.getActivity()
pourIntent
qui démarre uneActivity
.PendingIntent.getService()
pourIntent
qui démarre uneService
.PendingIntent.getBroadcast()
pourIntent
qui démarre uneBroadcastReceiver
.
Sauf si votre application reçoit des intents en attente provenant d'autres applications,
les méthodes ci-dessus pour créer un PendingIntent
sont probablement les seules
PendingIntent
.
Chaque méthode utilise l'Context
de l'application actuelle, le
Intent
que vous souhaitez encapsuler et un ou plusieurs indicateurs qui spécifient
la manière dont l'intent doit être utilisé (par exemple, s'il peut être utilisé plusieurs fois) ;
Pour en savoir plus sur l'utilisation des intents en attente, consultez la documentation de chacun des cas d'utilisation respectifs, par exemple dans les guides de l'API Notifications et Widgets d'application.
Spécifier la mutabilité
Si votre application cible Android 12 ou une version ultérieure, vous devez spécifier le
mutabilité de chaque objet PendingIntent
créé par votre application. Pour déclarer que
un objet PendingIntent
donné est modifiable ou immuable, utilisez
PendingIntent.FLAG_MUTABLE
ou
PendingIntent.FLAG_IMMUTABLE
.
Si votre application tente de créer un objet PendingIntent
sans définir aucun indicateur de mutabilité, le système génère une
IllegalArgumentException
et
le message suivant s'affiche dans Logcat:
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.
Dans la mesure du possible, créez des intents en attente immuables.
Dans la plupart des cas, votre application doit créer des objets PendingIntent
immuables, car
comme indiqué dans l'extrait de code suivant. Si un objet PendingIntent
est immuable,
alors les autres applications ne peuvent pas modifier l'intent pour ajuster le résultat de l'appel de la méthode
l'intention.
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);
Toutefois, certains cas d'utilisation nécessitent des objets PendingIntent
modifiables :
- Prise en charge des actions de réponse directe dans
notifications. La réponse directe nécessite une modification des données du clip dans l'objet PendingIntent associé à la réponse. En règle générale, vous demandez cette modification en transmettant
FILL_IN_CLIP_DATA
comme indicateur à la méthodefillIn()
. - Associer des notifications au framework Android Auto à l'aide d'instances de
CarAppExtender
- Placer des conversations dans des bulles à l'aide d'instances
sur
PendingIntent
. Un objetPendingIntent
modifiable permet au système d'appliquer les indicateurs appropriés, tels queFLAG_ACTIVITY_MULTIPLE_TASK
etFLAG_ACTIVITY_NEW_DOCUMENT
. - Demander les informations de localisation de l'appareil en appelant
requestLocationUpdates()
ou des API similaires. L'objetPendingIntent
modifiable permet au système d'ajouter des extras d'intent qui représentent des événements de cycle de vie d'emplacement. Ces événements incluent un de changement de lieu et à la disponibilité d’un fournisseur. - Programmer des alarmes avec
AlarmManager
. L'objetPendingIntent
modifiable permet au système d'ajouter leEXTRA_ALARM_COUNT
sur l'intention supplémentaire. Cet extra représente le nombre de fois qu'une alarme récurrente a été déclenchée. En contenant cet extra, l'intent peut notifier précisément une application pour savoir si une alarme récurrente a été déclenchée plusieurs fois, par exemple lorsque l'appareil était en veille.
Si votre appli crée un objet PendingIntent
modifiable, nous vous recommandons vivement
d'utiliser un intent explicite et de renseigner
ComponentName
De cette façon, chaque fois qu'une autre application appelle PendingIntent
et redonne le contrôle à votre application, le même composant de votre application démarre toujours.
Utiliser des intents explicites dans les intents en attente
Pour mieux définir comment d'autres applications peuvent utiliser les intents en attente de votre application, encapsulez toujours un intent en attente autour d'un intent explicite. Pour suivre cette bonne pratique, procédez comme suit :
- Vérifiez que les champs d'action, de package et de composant de l'intent de base sont définis.
-
Utilisez
FLAG_IMMUTABLE
, ajoutée dans Android 6.0 (niveau d'API 23), pour créer des intents en attente. Cet indicateur empêche les applis qui reçoivent unPendingIntent
de remplir non renseignées. Si l'minSdkVersion
de votre application est22
ou une version antérieure, vous pouvez assurer ensemble la sécurité et la compatibilité à l'aide du code suivant:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
Résolution d'intent
Lorsque le système reçoit un intent implicite pour démarrer une activité, il recherche la meilleure activité pour l'intent en le comparant aux filtres d'intent sur la base de trois aspects:
- action.
- Données (URI et type de données).
- Catégorie :
Les sections suivantes décrivent comment les intents sont associés aux composants appropriés conformément à la déclaration du filtre d'intent dans le fichier manifeste d'une application.
Test de l'action
Pour spécifier les actions d'intent acceptées, un filtre d'intent peut déclarer zéro ou plusieurs
<action>
, comme illustré dans l'exemple suivant:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
Pour que ce filtre soit validé, l'action spécifiée dans l'Intent
doit correspondre à l'une des actions répertoriées dans le filtre.
Si le filtre ne liste aucune action, aucun intent ne peut correspondre. Par conséquent, tous les intents échouent au test. Toutefois, si un Intent
ne spécifie pas d'action, l'opération réussit le test tant que le filtre
contient au moins une action.
Test de catégorie
Pour spécifier les catégories d'intent acceptées, un filtre d'intent peut déclarer zéro ou plusieurs
<category>
, comme illustré dans l'exemple suivant:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
Pour qu'un intent réussisse le test de catégorie, chaque catégorie de Intent
doit correspondre à une catégorie du filtre. L'inverse n'est pas nécessaire : le filtre d'intent peut déclarer plus de catégories que celles spécifiées dans le Intent
, et le Intent
est toujours accepté. Par conséquent, un intent sans catégorie
réussit toujours ce test, quelles que soient les catégories déclarées dans le filtre.
Remarque:
Android applique automatiquement la catégorie CATEGORY_DEFAULT
à tous les intents implicites transmis à startActivity()
et startActivityForResult()
.
Si vous souhaitez que votre activité reçoive des intents implicites, elle doit
inclure une catégorie pour "android.intent.category.DEFAULT"
dans ses filtres d'intent, comme
comme indiqué dans l'exemple <intent-filter>
précédent.
Test de données
Pour spécifier les données d'intent acceptées, un filtre d'intent peut déclarer zéro ou plusieurs
<data>
, comme illustré dans l'exemple suivant:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
Chaque <data>
peut spécifier une structure d'URI et un type de données (type de média MIME).
Chaque partie de l'URI est un sous-réseau
attribut: scheme
, host
, port
,
et path
:
<scheme>://<host>:<port>/<path>
L'exemple suivant indique les valeurs possibles pour ces attributs:
content://com.example.project:200/folder/subfolder/etc
Dans cet URI, le schéma est content
, l'hôte est com.example.project
,
le port est 200
et le chemin d'accès est folder/subfolder/etc
.
Chacun de ces attributs est facultatif dans un élément <data>
.
mais il existe des dépendances linéaires:
- Si aucun schéma n'est spécifié, l'hôte est ignoré.
- Si aucun hôte n'est spécifié, le port est ignoré.
- Si le schéma et l'hôte ne sont pas spécifiés, le chemin d'accès est ignoré.
Lorsque l'URI d'un intent est comparé à une spécification d'URI dans un filtre, il est comparé uniquement aux parties de l'URI incluses dans le filtre. Exemple :
- Si un filtre ne spécifie qu'un schéma, tous les URI avec ce schéma correspondent. le filtre.
- Si un filtre spécifie un schéma et une autorité, mais pas de chemin d'accès, tous les URI ayant le même schéma et la même autorité passent le filtre, quels que soient leurs chemins.
- Si un filtre spécifie un schéma, une autorité et un chemin d'accès, mais uniquement des URI présentant le même schéma, l'autorité et le chemin d'accès passent le filtre.
Remarque:Une spécification de chemin d'accès peut contenir un caractère générique astérisque (*) pour ne nécessiter qu'une correspondance partielle du nom de chemin.
Le test de données compare à la fois l'URI et le type MIME de l'intent à un URI et un type MIME spécifiés dans le filtre. Les règles sont les suivantes:
- Un intent qui ne contient ni un URI ni un type MIME transmet la tester uniquement si le filtre ne spécifie aucun URI ou type MIME.
- Un intent contenant un URI, mais pas de type MIME (ni explicite, ni inférable à partir de URI) ne réussit le test que si son URI correspond au format d'URI du filtre. et le filtre ne spécifie pas de type MIME.
- Un intent contenant un type MIME, mais pas d'URI, réussit le test uniquement si le filtre répertorie le même type MIME et ne spécifie pas de format d'URI.
- Un intent contenant à la fois un URI et un type MIME (explicite ou inférable à partir du
URI) ne réussit la partie du test concernant le type MIME que si cette
type correspond à un type répertorié dans le filtre. Il passe la partie URI du test
soit si son URI correspond à un URI du filtre ou s'il possède un
content:
oufile:
, et que le filtre ne spécifie pas d'URI. Autrement dit, un composant est supposé prendre en charge les donnéescontent:
etfile:
si son filtre répertorie uniquement un type MIME.
Remarque:Si un intent spécifie un URI ou un type MIME, le test de données
échoue s'il n'y a pas d'éléments <data>
dans <intent-filter>
.
Cette dernière règle, la règle (d), reflète les attentes
que les composants sont capables d'obtenir des données locales
d'un fournisseur de fichier ou de contenu.
Par conséquent, leurs filtres peuvent ne répertorier qu'un type de données et n'ont pas besoin d'indiquer explicitement
Nommez les schémas content:
et file:
.
L'exemple suivant montre un cas typique dans lequel un élément <data>
indique à Android que le composant peut obtenir des données d'image auprès d'un fournisseur de contenu et les afficher :
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
Les filtres qui spécifier un type de données, mais pas d'URI sont peut-être les plus courants, car la plupart des les données sont fournies par les fournisseurs de contenu.
Une autre configuration courante est un filtre avec un schéma et un type de données. Pour
par exemple, un <data>
comme celui ci-dessous, indique à Android que
Le composant peut récupérer des données vidéo sur le réseau pour effectuer l'action:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
Correspondance d'intent
Les intents sont mis en correspondance avec des filtres d'intent non seulement pour découvrir une cible
à activer, mais aussi de découvrir des informations sur l'ensemble
composants de l'appareil. Par exemple, l'application Home remplit le lanceur d'applications.
en recherchant toutes les activités avec des filtres d'intent qui spécifient
ACTION_MAIN
action et
Catégorie CATEGORY_LAUNCHER
.
Une correspondance n'est réussie que si les actions et les catégories de l'intent correspondent au filtre, comme décrit dans la documentation de la classe IntentFilter
.
Votre application peut utiliser la mise en correspondance des intents de la même manière que l'application Home.
PackageManager
a un ensemble de query...()
qui renvoient tous les composants pouvant accepter un intent particulier.
une série similaire de méthodes resolve...()
, qui déterminent
pour répondre à un intent. Par exemple, queryIntentActivities()
renvoie la liste de toutes les activités pouvant effectuer l'intent transmis en tant qu'argument, et queryIntentServices()
renvoie une liste similaire de services.
Aucune de ces deux méthodes n'active les composants. ils énumèrent simplement ceux qui
peuvent répondre. Il existe une méthode similaire,
queryBroadcastReceivers()
, pour les broadcast receivers