Diriger l'utilisateur vers une autre application

L'une des fonctionnalités les plus importantes d'Android est la capacité d'une application à rediriger l'utilisateur vers une autre application en fonction d'une "action" qu'il souhaite effectuer. Par exemple, si votre application contient l'adresse d'une entreprise que vous souhaitez afficher sur une carte, vous n'avez pas besoin de créer une activité qui affiche une carte. À la place, vous pouvez créer une requête pour afficher l'adresse à l'aide d'un élément Intent. Le système Android démarre ensuite une application capable d'afficher l'adresse sur une carte.

Comme expliqué dans la première leçon, Créer votre première application, vous devez utiliser des intents pour naviguer entre les activités de votre propre application. En général, vous le faites avec un intent explicite, qui définit le nom de classe exact du composant que vous souhaitez démarrer. Toutefois, lorsque vous souhaitez qu'une application distincte effectue une action telle que "voir une carte", vous devez utiliser un intent implicite.

Cette leçon explique comment créer un intent implicite pour une action particulière et l'utiliser pour lancer une activité qui effectue cette action dans une autre application. Consultez également la vidéo intégrée ici pour comprendre pourquoi il est important d'inclure des vérifications d'exécution pour vos intents implicites.

Créer un intent implicite

Les intents implicites ne déclarent pas le nom de classe du composant pour démarrer, mais déclarent une action à effectuer. L'action spécifie ce que vous souhaitez faire, par exemple view, edit, send ou get.

Associer des actions d'intent aux données

Les intents incluent souvent les données associées à l'action, telles que l'adresse que vous souhaitez afficher ou le message électronique que vous souhaitez envoyer. Selon l'intent que vous souhaitez créer, les données peuvent correspondrent à une Uri ou à l'un des nombreux autres types de données. Il est également possible que l'intent n'ait pas du tout besoin de données.

Si vos données correspondent à une Uri, il existe un constructeur Intent() simple que vous pouvez utiliser pour définir l'action et les données.

Par exemple, voici comment créer un intent pour lancer un appel téléphonique à l'aide des données d'une Uri afin de spécifier le numéro de téléphone :

Kotlin

val callIntent: Intent = Uri.parse("tel:5551234").let { number ->
    Intent(Intent.ACTION_DIAL, number)
}

Java

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

Lorsque votre application appelle cet intent en appelant startActivity(), elle appelle le numéro de téléphone indiqué.

Voici quelques autres intents, ainsi que leurs paires de données action-Uri :

Afficher un plan

Kotlin

// Map point based on address
val mapIntent: Intent = Uri.parse(
        "geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"
).let { location ->
    // Or map point based on latitude/longitude
    // val location: Uri = Uri.parse("geo:37.422219,-122.08364?z=14") // z param is zoom level
    Intent(Intent.ACTION_VIEW, location)
}

Java

// Map point based on address
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

Afficher une page Web

Kotlin

val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage ->
    Intent(Intent.ACTION_VIEW, webpage)
}

Java

Uri webpage = Uri.parse("https://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

Compléter un intent

D'autres types d'intents implicites nécessitent des données "supplémentaires" qui fournissent différents types de données, tels qu'une chaîne. Vous pouvez ajouter un ou plusieurs éléments de données supplémentaires à l'aide des différentes méthodes putExtra().

Par défaut, le système détermine le type MIME approprié requis par un intent en fonction des données d'Uri incluses. Si vous n'incluez pas d'Uri dans l'intent, vous devez généralement utiliser setType() pour spécifier le type de données associé à l'intent. La définition du type MIME spécifie également les types d'activités qui doivent recevoir l'intent.

Voici d'autres intents qui ajoutent des données supplémentaires pour spécifier l'action souhaitée :

Envoyer un e-mail avec une pièce jointe

Kotlin

Intent(Intent.ACTION_SEND).apply {
    // The intent does not have a URI, so declare the "text/plain" MIME type
    type = "text/plain"
    putExtra(Intent.EXTRA_EMAIL, arrayOf("jan@example.com")) // recipients
    putExtra(Intent.EXTRA_SUBJECT, "Email subject")
    putExtra(Intent.EXTRA_TEXT, "Email message text")
    putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"))
    // You can also attach multiple items by passing an ArrayList of Uris
}

Java

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jan@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris

Créer un événement d'agenda

Remarque : Cet intent pour un événement d'agenda n'est compatible qu'avec les API de niveau 14 ou supérieur.

Kotlin

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply {
    val beginTime: Calendar = Calendar.getInstance().apply {
        set(2021, 0, 23, 7, 30)
    }
    val endTime = Calendar.getInstance().apply {
        set(2021, 0, 23, 10, 30)
    }
    putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.timeInMillis)
    putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.timeInMillis)
    putExtra(Events.TITLE, "Ninja class")
    putExtra(Events.EVENT_LOCATION, "Secret dojo")
}

Java

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance();
beginTime.set(2021, 0, 23, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2021, 0, 23, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

Remarque : Il est important que votre Intent soit aussi spécifique que possible. Par exemple, si vous souhaitez afficher une image à l'aide de l'intent ACTION_VIEW, vous devez spécifier le type MIME d'image/*. Cela empêche les applications qui peuvent "consulter" d'autres types de données (comme une application de carte) d'être déclenchées par l'intent.

Démarrer une activité avec l'intent

Une fois que vous avez créé votre Intent et défini les informations supplémentaires, appelez startActivity() pour les envoyer au système :

Kotlin

startActivity(intent)

Java

startActivity(intent);

Gérer l'incapacité des applications à recevoir des intents

Bien que de nombreux intents soient correctement gérés par les autres applications installées sur l'appareil (telle qu'une application d'appel, de messagerie ou d'agenda), votre application doit se préparer au cas où aucune activité ne pourra gérer l'intent de votre application. Chaque fois que vous appelez un intent, préparez-vous à intercepter une ActivityNotFoundException, qui se produit si aucune autre activité ne peut gérer l'intent de votre application :

Kotlin

try {
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

try {
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Une fois que vous avez identifié cette exception, déterminez la procédure à suivre pour votre application. L'étape suivante dépend des caractéristiques spécifiques de l'intent que vous avez essayé d'appeler. Par exemple, si vous connaissez une application spécifique capable de gérer l'intent, fournissez un lien permettant à l'utilisateur de télécharger l'application. Découvrez comment associer vos produits sur Google Play.

Boîte de dialogue de sélection d'application

Si le système identifie plusieurs activités capables de gérer l'intent, il affiche une boîte de dialogue (parfois appelée "boîte de dialogue de sélection d'application") qui permet à l'utilisateur de sélectionner l'application à utiliser, comme illustré dans la figure 1. Si une seule activité gère l'intent, le système la lance immédiatement.

Un panneau apparaît en bas de l'écran. Ce panneau liste les différentes applications susceptibles de gérer l'intent.

Figure 1. Exemple de boîte de dialogue de sélection qui s'affiche lorsque plusieurs applications peuvent gérer un intent.

Exemple complet

Voici un exemple complet qui montre comment créer un intent pour afficher une carte, vérifier qu'une application existe pour gérer l'intent, puis la démarrer :

Kotlin

// Build the intent.
val location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California")
val mapIntent = Intent(Intent.ACTION_VIEW, location)

// Try to invoke the intent.
try {
    startActivity(mapIntent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

// Build the intent.
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// Try to invoke the intent.
try {
    startActivity(mapIntent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Afficher un sélecteur d'application

Figure 2. Boîte de dialogue de sélection.

Notez que lorsque vous démarrez une activité en transmettant votre Intent à startActivity() et que plusieurs applications répondent à l'intent, l'utilisateur peut sélectionner l'application à utiliser par défaut (en cochant une case en bas de la boîte de dialogue ; voir la figure 1). C'est utile lorsque vous effectuez une action pour laquelle l'utilisateur souhaite généralement utiliser la même application à chaque fois, par exemple lorsqu'il ouvre une page Web (il est probable que les utilisateurs n'utilisent qu'un seul navigateur Web) ou qu'ils prennent une photo (les utilisateurs sont susceptibles préférez un seul appareil photo).

Cependant, si l'action à effectuer peut être gérée par plusieurs applications et que l'utilisateur peut préférer une application différente à chaque fois (par exemple, une action de partage, pour laquelle les utilisateurs peuvent avoir plusieurs applications via lesquelles ils peuvent partager un élément). Vous devriez afficher explicitement une boîte de dialogue de sélection, comme illustré dans l'image 2. La boîte de dialogue du sélecteur oblige l'utilisateur à sélectionner l'application à utiliser à chaque fois (il ne peut pas sélectionner une application par défaut pour l'action).

Pour afficher le sélecteur, créez un Intent à l'aide de createChooser() et transmettez-le à startActivity(). Par exemple :

Kotlin

val intent = Intent(Intent.ACTION_SEND)

// Create intent to show chooser
val chooser = Intent.createChooser(intent, /* title */ null)

// Try to invoke the intent.
try {
    startActivity(chooser)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);

// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, /* title */ null);

// Try to invoke the intent.
try {
    startActivity(chooser);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Cette action affiche une boîte de dialogue contenant la liste des applications qui répondent à l'intent transmis à la méthode createChooser(). Le paramètre title peut être fourni si l'action n'est pas ACTION_SEND ou ACTION_SEND_MULTIPLE.