Création de filtres d'Intents pour recevoir des Intents implicites

 Lorsqu'un objectif d'activité est une demande d'exécution d'une action sur un ensemble de données, un filtre d'intention est la déclaration correspondante attestant qu'une activité est capable d'effectuer une action sur un type de données. Comme vous le verrez plus loin dans ce chapitre, les filtres d'intention sont également utilisés par les récepteurs de diffusion pour indiquer les actions de diffusion qu'ils souhaitent recevoir.

 Définir un filtre d'Intents

À l'aide des filtres d'Intents, les activités peuvent déclarer les actions et les données qu'elles peuvent prendre en charge. Pour enregistrer une activité en tant que gestionnaire d'Intents potentiel, ajoutez une balise d'Intents-filtre à son nœud manifeste à l'aide des balises suivantes (et des attributs associés):

  • action: utilise l'attribut android : name pour spécifier le nom de l'action pouvant être effectuée. Chaque filtre d'Intents doit avoir au moins une balise d'action et les actions doivent être des chaînes uniques auto-descriptives.    Vous pouvez définir vos propres actions (la meilleure pratique consiste à utiliser un système de nommage basé sur les conventions d'appellation du package Java) ou à utiliser l'une des actions système fournies par Android.
  • data : la balise de données vous permet de spécifier les types de données sur lesquels votre composant peut agir; vous pouvez inclure plusieurs balises de données selon vos besoins.

Vous pouvez utiliser n'importe quelle combinaison des attributs suivants pour spécifier les données prises en charge par votre composant:

  • android: hôte : spécifie un nom d'hôte valide (par exemple, google.com).
  • android: mimetype : spécifie le type de données que votre composant est capable de gérer. Par exemple, vnd.android.cursor.dir / * correspond à n’importe quel curseur Android.
  • android: path : spécifie les valeurs de chemin valides pour l'URI (par exemple, / transport / boats /).
  • android: port : spécifie les ports valides pour l'hôte spécifié.
  • android: scheme : nécessite un schéma particulier (contenu ou http, par exemple). 

L'extrait suivant montre un filtre d'Intents pour une activité pouvant exécuter l'action SHOW_DAMAGE en tant qu'action principale ou alternative en fonction de son type mime de curseur tremblement de terre:

  1. < intent-filter >
  2. <action
  3. android:name="com.paad.earthquake.intent.action.SHOW_DAMAGE"/>
  4. <category
  5. android:name="android.intent.category.DEFAULT"/>
  6. <category
  7. android:name="android.intent.category.SELECTED_ALTERNATIVE"/>
  8. <data android:mimeType="vnd.android.cursor.item/vnd.com.professionalandroid.provider.earthquake"
  9. />
  10. < /intent-filter >

 Vous avez peut-être remarqué que cliquer sur un lien vers une vidéo YouTube ou un emplacement Google Maps sur un appareil Android vous invite à utiliser respectivement YouTube ou Google Maps, plutôt qu'un navigateur Web. Ceci est réalisé en spécifiant les attributs de schéma, d'hôte et de chemin dans la balise de données d'un filtre d'intention, comme indiqué dans le Listing 6-7. Dans cet exemple, tout lien du formulaire commençant par http: // blog.radioactiveyak.com peut être desservi par cette activité.

 LISTING 6-7: Enregistrement d’une activité en tant que récepteur d'Intents pour visualiser le contenu d’un site Web spécifique à l’aide d’un filtre d’inTention  

 

  1. < activity android:name=".MyBlogViewerActivity" >
  2. <intent-filter>
  3. <action android:name="android.intent.action.VIEW" />
  4. <category android:name="android.intent.category.DEFAULT" />
  5. <category android:name="android.intent.category.BROWSABLE" />
  6. <data android:scheme="http"
  7. android:host="blog.radioactiveyak.com"/>
  8. </intent-filter>
  9. < /activity >

 Notez que vous devez inclure la catégorie navigable pour que les liens sur lesquels vous avez cliqué dans le navigateur déclenchent ce comportement.

 Comment Android résout les Intents à l'aide de filtres d'Intents

  1. Le processus de décision de l'activité à démarrer lorsqu'une Intents implicite est transmise à startActivity est appelé résolution d'intention. Le but de la résolution d'Intents est de trouver la meilleure correspondance de filtre d'Intents possible à l'aide du processus suivant: 
  2. Android dresse une liste de tous les filtres d'Intents disponibles dans les packages installés. 
  3. Intent Les filtres qui ne correspondent pas à l'action ou à la catégorie associée à l'intent en cours de résolution sont supprimés de la liste. Matches Les correspondances d'action sont effectuées uniquement si le filtre d'intention inclut l'action spécifiée. Un filtre d'Intents échouera à la vérification de la correspondance d'action si aucune de ses actions ne correspond à celle spécifiée par l'intention. Pour la correspondance des catégories, les filtres d'Intents doivent inclure toutes les catégories définies dans l'Intent de résolution, mais peuvent inclure des catégories supplémentaires non incluses dans l'Intent. Un filtre d'Intents sans catégorie spécifiée ne correspond qu'à des intentions sans catégorie.
  4. Chaque partie de l’URI de données de l’intention est comparée à la balise de données du filtre d’intention. Si le filtre d’intention spécifie un schéma, un hôte / une autorité, un chemin ou un type MIME, ces valeurs sont comparées à l’URI de l’Intent. Toute incompatibilité supprimera le filtre d'intention de la liste. Si vous ne spécifiez aucune valeur dans un filtre d'Intents, vous obtiendrez une correspondance avec toutes les valeurs de données d'Intents. 

Le type MIME est le type de données des données en correspondance. Lors de la correspondance des types de données, vous pouvez utiliser des caractères génériques pour faire correspondre les sous-types. Si le filtre d'Intents spécifie un type de données, il doit correspondre à l'Intent ; Si vous ne spécifiez aucun type de données, vous obtenez une correspondance avec tous les types.  

Scheme Le schéma est la partie «protocole» de l'URI (par exemple, http :, mailto:, ou tel :).  

Le nom d'hôte ou l'autorité de données correspond à la section de l'URI située entre le schéma et le chemin d'accès (par exemple, developer.android.com). Pour qu’un nom d’hôte corresponde, le schéma du filtre d’intention doit également correspondre. Si aucun schéma n'est spécifié, le nom d'hôte est ignoré.  

Le chemin de données est ce qui vient après l'autorité (par exemple, / training). Un chemin ne peut correspondre que si les parties schéma et nom d'hôte de la balise de données correspondent également.  

Lorsque vous démarrez implicitement une activité, si plusieurs processus sont résolus à partir de ce processus, toutes les possibilités de correspondance sont offertes à l'utilisateur. Les composants d'application Android natifs font partie du processus de résolution d'Intents exactement de la même manière que les applications tierces. Elles n'ont pas une priorité plus élevée et peuvent être complètement remplacées par de nouvelles activités déclarant des filtres d'intention servant les mêmes actions. En conséquence, lors de la définition d'un filtre d'Intents indiquant que votre application peut afficher les liens URL, le navigateur reste proposé (en plus de votre application).

 Recherche et utilisation des Intents dans une activité

 Lorsqu'une activité est démarrée via une intention implicite, elle doit rechercher l'action à exécuter et les données nécessaires à son exécution. Pour rechercher l'intention utilisée pour démarrer l'activité, appelez getIntent, comme indiqué dans le listing 6-8.

 LISTING 6-8 : Trouver l'Intent de lancement d'une activité

 

  1. @Override
  2. public void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.main);
  5. Intent intent = getIntent();
  6. String action = intent.getAction();
  7. Uri data = intent.getData();
  8. }

 Utilisez les méthodes getData et getAction pour rechercher les données et l'action associées à l'intention. Utilisez les méthodes type-safe get <type> Extra pour extraire des informations supplémentaires stockées dans ses extras Bundle. 

La méthode getIntent renverra toujours l'intention initiale utilisée pour créer l'activité. Dans certaines circonstances, votre activité peut continuer à recevoir des intentions après son lancement. 

Par exemple, si votre application passe en arrière-plan, l'utilisateur peut cliquer sur une notification pour ramener l'application en cours au premier plan, ce qui entraîne la création d'une nouvelle intention dans l'activité correspondante. Si votre activité est configurée de telle sorte que lors de la relance, au lieu de créer une nouvelle instance, l'instance existante est déplacée en haut de la pile d'activités, une nouvelle intention est livrée via le gestionnaire onNewIntent. Vous pouvez appeler setIntent pour mettre à jour l'Intent renvoyée lorsque vous appelez getIntent:

 

  1. @Override
  2. public void onNewIntent(Intent newIntent) {
  3. // TODO React to the new Intent
  4. setIntent(newIntent); super.onNewIntent(newIntent); }

 Sélection d'un exemple de signe en étoile

 Dans cet exemple, vous créez une nouvelle activité desservant ACTION_PICK pour une liste de signes en étoile. L'application de sélection affiche une liste de signes en étoile et permet à l'utilisateur d'en sélectionner un avant de fermer et de renvoyer le signe sélectionné à l'activité appelante. REMARQUE Comme pour les exemples précédents, afin de simplifier la lisibilité, toutes les instructions d'importation requises ne sont pas incluses dans ces étapes. Vous pouvez activer «ajouter automatiquement des importations non ambiguës à la volée» dans les paramètres d'Android Studio ou appuyez sur Alt + Entrée pour chaque nom de classe non résolu, selon les besoins. 

1- Créez un nouveau projet StarSignPicker comprenant une activité StarSignPicker basée sur le modèle d'activité vide et utilisant la bibliothèque de compatibilité des applications. Ajoutez une constante de chaîne EXTRA_SIGN_NAME qui sera utilisée pour stocker un extra dans notre Intent de retour pour indiquer le signe en étoile sélectionné par l'utilisateur:

 

  1. public class StarSignPicker extends AppCompatActivity {
  2. public static final String EXTRA_SIGN_NAME = "SIGN_NAME";
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_star_sign_picker);
  7. }
  8. }

2- Modifiez la ressource de présentation activity_star_sign_picker.xml pour inclure un seul contrôle RecyclerView. Ce contrôle sera utilisé pour afficher les contacts:

 

  1. < ?xml version="1.0" encoding="utf-8"? >
  2. < android.support.v7.widget.RecyclerView
  3. xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:id="@+id/recycler_view"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. app:layoutManager="LinearLayoutManager" />

3- Créez une nouvelle ressource de présentation list_item_layout.xml basée sur un FrameLayout comprenant un seul contrôle TextView. Ce contrôle sera utilisé pour afficher chaque signe étoile dans la vue Recycler:

 

  1. < ?xml version="1.0" encoding="utf-8"? >
  2. < FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content">
  5.  
  6. <TextView
  7. android:id="@+id/itemTextView"
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:layout_margin="8dp"
  11. android:textAppearance="?attr/textAppearanceListItem"/> < /FrameLayout >

4- Ajoutez la bibliothèque Recycler View au fichier de construction Gradle de votre module d'application:

 

  1. dependencies {
  2.  
  3. [... Existing dependencies ...] implementation 'com.android.support:recyclerview-v7:27.1.1' }
  4.  
  5.  

5-        Créez une nouvelle classe StarSignPickerAdapter qui étend RecyclerView.Adapter et qui contient un tableau de chaînes de signes en étoile:

 

  1. public class StarSignPickerAdapter
  2. extends RecyclerView.Adapter<StarSignPickerAdapter.ViewHolder> {
  3. private String[] mStarSigns = {"Aries", "Taurus", "Gemini", "Cancer","Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius","Pisces" };
  4. public StarSignPickerAdapter() {
  5. }
  6. @Override
  7. public int getItemCount() {
  8. return mStarSigns == null ? 0 : mStarSigns.length;
  9. }
  10. }

 5.1 Dans l’Adaptateur créé à l’étape 5, créez une nouvelle classe ViewHolder qui étend RecyclerView.ViewHolder et implémente un OnClickListener. Il devrait exposer un TextView et un OnClickListener:

 

  1. public static class ViewHolder extends
  2. RecyclerView.ViewHolder
  3. implements View.OnClickListener {
  4. public TextView textView;
  5. public View.OnClickListener mListener;
  6. public ViewHolder(View v, View.OnClickListener listener) {
  7. super(v); mListener = listener;
  8. textView = v.findViewById(R.id.itemTextView);
  9. v.setOnClickListener(this);
  10. }
  11. @Override
  12. public void onClick(View v) {
  13. if (mListener != null)
  14. mListener.onClick(v);
  15. }
  16. }

5.2 Toujours dans l'adaptateur, remplacez onCreateViewHolder à l'aide du ViewHolder créé à l'étape 5.1, en gonflant l'élément list_item_layout créé à l'étape 3:

 

  1. @Override
  2. public StarSignPickerAdapter.ViewHolder
  3. onCreateViewHolder(ViewGroup parent, int viewType) {
  4. // Create the new View
  5. View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_layout, parent,false);
  6. return new ViewHolder(v, null); }

 5.3 Créer une nouvelle interface contenant une méthode onItemClicked prenant une chaîneargument; ajoutez une méthode setOnAdapterItemClick à l'adaptateur pour stocker une référence à ce gestionnaire d'événements. Nous utiliserons ce gestionnaire pour notifier à l'activité parente quel élément de la liste a été sélectionné :

 

  1. public interface IAdapterItemClick {
  2. void onItemClicked(String selectedItem);
  3. }
  4. IAdapterItemClick mAdapterItemClickListener;
  5. public void setOnAdapterItemClick(
  6. IAdapterItemClick adapterItemClickHandler) {
  7. mAdapterItemClickListener = adapterItemClickHandler;
  8. }

 5.4 Enfin, substituez la méthode onBindViewHolder de l’adaptateur en affectant un signe en étoile àla vue de texte définie dans notre détenteur de vue. Saisissez cette opportunité pour implémenter onClickListener pour chaque détenteur de vue, qui appellera le gestionnaire IAdapterItemClick à l’étape 5.3 si un élément de notre liste est cliqué:

 

  1. @Override
  2. public void onBindViewHolder(ViewHolder holder, final int position) {
  3. holder.textView.setText(mStarSigns[position]);
  4. holder.mListener = new View.OnClickListener() {
  5. @Override
  6. public void onClick(View v) {
  7. if (mAdapterItemClickListener != null)
  8. mAdapterItemClickListener.onItemClicked(mStarSigns[position]);
  9. }
  10. };
  11. }

6-  Revenez à l'activité StarSignPicker et modifiez la méthode onCreate. Cela commence actuellement comme ça:

 

 a) une. Maintenant, toujours dans onCreate, instanciez le StarSignPickerAdapter que vous avez créé à l'étape 5: 

  1. StarSignPickerAdapter adapter = new StarSignPickerAdapter() ;

 b) Créez un nouveau gestionnaire IAdapterItemClick et affectez-le à l'adaptateur à l'aide duMéthode setOnAdapterItemClick. Lorsque vous cliquez sur un élément, créez un nouveau résultat d'intention et utilisez la chaîne EXTRA_SIGN_NAME pour affecter un extra contenant le signe en étoile sélectionné. Attribuez la nouvelle intention comme résultat de cette activité à l'aide de setResult et de la fin de l'appel pour fermer l'activité et revenir à l'appelant:

 

  1. adapter.setOnAdapterItemClick(
  2. new StarSignPickerAdapter.IAdapterItemClick() {
  3. @Override
  4. public void onItemClicked(String selectedItem) {
  5. // Construct the result URI.
  6. Intent outData = new Intent();
  7. outData.putExtra(EXTRA_SIGN_NAME, selectedItem);
  8. setResult(Activity.RESULT_OK, outData);
  9. finish();
  10. }
  11. }) ;

 6.3 Affectez l'adaptateur à la vue Recycler à l'aide de setAdapter:

  1. RecyclerView rv = findViewById(R.id.recycler_view); rv.setAdapter(adapter);

 6.4 Fermer la méthode onCreate

 }

 7. Modifiez le manifeste de l'application et remplacez la balise intent-filter de Activity pour ajouter la prise en charge de l'action ACTION_PICK sur les signes en étoile:

 

  1. < activity android:name=".StarSignPicker" >
  2. <intent-filter>
  3. <action android:name="android.intent.action.PICK" />
  4. <category android:name="android.intent.category.DEFAULT"/>
  5. <data android:scheme="starsigns" />
  6. </intent-filter>
  7. < /activity >

 8. Ceci termine la sous-activité. Pour le tester, créez une nouvelle activité de lancement du faisceau de test StarSignPickerTester avec un fichier de mise en forme activity_star_sign_picker_tester.xml. Mettez à jour la mise en page pour inclure un TextView pour afficher le signe en étoile sélectionné et un bouton pour démarrer la sous-activité:

 

  1. < ?xml version="1.0" encoding="utf-8"? >
  2. < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent">
  6. <TextView
  7. android:id="@+id/selected_starsign_textview"
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:textAppearance="?attr/textAppearanceListItem"
  11. android:layout_margin="8dp"
  12. /> <Button android:id="@+id/pick_starsign_button"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Pick Star Sign"/>
  13. < /LinearLayout >

 9. Remplacez la méthode onCreate de StarSignPickerTester afin d’ajouter un écouteur de clic au bouton afin qu’il commence implicitement une nouvelle sous-activité en spécifiant ACTION_PICK et en signant le schéma de données:

 

  1. public class StarSignPickerTester extends AppCompatActivity {
  2. public static final int PICK_STARSIGN = 1;
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_star_sign_picker_tester);
  7. Button button = findViewById(R.id.pick_starsign_button);
  8. button.setOnClickListener(new View.OnClickListener() {
  9. @Override
  10. public void onClick(View _view) {
  11. Intent intent = new Intent(Intent.ACTION_PICK, Uri.parse("starsigns://"));
  12. startActivityForResult(intent, PICK_STARSIGN);
  13. }
  14. });
  15. }
  16. }

 10. Lorsque la sous-activité revient, utilisez le résultat pour renseigner la vue texte avec le signe étoile sélectionné:

 

  1. @Override
  2. public void onActivityResult(int reqCode, int resCode, Intent data) {
  3. super.onActivityResult(reqCode, resCode, data);
  4. switch(reqCode) {
  5. case (PICK_STARSIGN) : {
  6. if (resCode == Activity.RESULT_OK) {
  7. String selectedSign = data.getStringExtra(StarSignPicker.EXTRA_SIGN_NAME);
  8. TextView tv = findViewById(R.id.selected_starsign_textview);
  9. tv.setText(selectedSign);
  10. }
  11. break;
  12. }
  13. default: break;
  14. }
  15. }

 Lorsque votre activité de test est en cours, appuyez sur le bouton «Choisir un signe en étoile». Le sélecteur de signe en étoile Activité doit apparaître, comme illustré à la figure 6-1. Une fois que vous avez sélectionné un signe en forme d'étoile, l'activité parent doit revenir au premier plan avec la sélection affichée (voir Figure 6-2).

 Utilisation de filtres d'Intents pour les plug-ins et l'extensibilité

 Après avoir utilisé les filtres d'intention pour déclarer les actions que vos activités peuvent effectuer sur différents types de données, il va de soi que les applications peuvent également rechercher les actions pouvant être effectuées sur une donnée particulière. Android fournit un modèle de plug-in qui permet à vos applications de tirer parti des fonctionnalités fournies anonymement à partir de composants d’application propres ou tiers que vous n’avez pas encore conçus, sans que vous ayez à modifier ou à recompiler vos projets.

 Fournir des actions anonymes aux applications

 Pour utiliser ce mécanisme afin que vos actions Activity soient disponibles de manière anonyme pour les applications existantes, publiez-les à l’aide des balises d’intention-filter dans leurs nœuds de manifeste, comme décrit précédemment. Le filtre d'intention décrit l'action qu'il effectue et les données sur lesquelles il peut être exécuté. Ce dernier sera utilisé lors du processus de résolution d'intention pour déterminer quand cette action devrait être disponible. L’étiquette de catégorie doit être ALTERNATIVE ou SELECTED_ALTERNATIVE, ou les deux. L'attribut android : label doit être une étiquette lisible par l'homme qui décrit l'action.

 Remarque La catégorie ALTERNATIVE indique que l'action décrite est une alternative à ce que l'utilisateur est en train de voir. Il est utilisé pour indiquer une action à afficher dans un ensemble de tâches que l'utilisateur peut effectuer, généralement dans le cadre d'un menu d'options. La catégorie SELECTED_ALTERNATIVE est similaire mais indique une action généralement effectuée sur un élément sélectionné affiché dans une liste..    La liste 6-9 montre un exemple de filtre d’intention utilisé pour annoncer la capacité d’une activité à neutraliser les bases de Moon de l’orbite.

 LISTING 6-9 : Actions d'activité soutenues par la publicité

 

  1. < activity android:name=".NostromoController" >
  2. <intent-filter
  3. android:label="Nuke From Orbit">
  4. <action
  5. android:name="com.professionalandroid.nostromo.NUKE_FROM_ORBIT"/>
  6. <data android:mimeType="vnd.android.cursor.item/vnd.com.professionalandroid.provider.moonbase"
  7. />
  8. <category android:name="android.intent.category.ALTERNATIVE"/>
  9. <category
  10. android:name="android.intent.category.SELECTED_ALTERNATIVE"
  11. />
  12. </intent-filter>
  13. < /activity >

 Découverte de nouvelles actions de destinataires tiers

 À l'aide du gestionnaire de packages, vous pouvez créer une intention qui spécifie un type de données et une catégorie d'action, et demander au système de renvoyer une liste d'activités capables d'effectuer une action sur ces données. L’élégance de ce concept s’explique mieux par un exemple. Si les données affichées par votre activité sont une liste d’endroits, vous pouvez inclure une fonctionnalité permettant de les afficher sur une carte ou de «Afficher les directions pour». Quelques mois à l’avance, vous avez créé une application qui s’interface avec votre voiture et permet à votre téléphone de définir la destination de la conduite automatique. Grâce à la génération du menu d'exécution, lorsqu'un nouveau filtre d'intention, comportant une action DRIVE_CAR, est inclus dans le nouveau nœud de l'activité, Android résout cette nouvelle action et la met à la disposition de votre application précédente. Cela vous permet d’ajouter des fonctionnalités à votre application lorsque vous créez de nouveaux composants capables d’exécuter des actions sur un type de données donné. L'intention que vous créez sera utilisée pour résoudre les composants avec des filtres d'intention qui fournissent des actions pour les données que vous spécifiez. L’intention est utilisée pour rechercher des actions, aussi ne l’attribuez pas; il ne doit spécifier que les données sur lesquelles effectuer des actions. Vous devez également spécifier la catégorie de l'action, CATEGORY_ALTERNATIVE ou CATEGORY_SELECTED_ALTERNATIVE. Le code squelette permettant de créer une intention de résolution d’action de menu est présenté ici:

  1. Intent intent = new Intent();
  2. intent.setData(MyProvider.CONTENT_URI);
  3. intent.addCategory(Intent.CATEGORY_ALTERNATIVE);

 Transmettez cette intention à la méthode du gestionnaire de packages, queryIntentActivityOptions, en spécifiant les indicateurs d'options.  Le Listing 6-10 montre comment générer une liste d'actions à rendre disponibles dans votre application.

 LISTING 6-10 : Générer une liste d'actions possibles à exécuter sur des données spécifiques

 

  1. PackageManager packageManager = getPackageManager();
  2. // Create the intent used to resolve which actions // should appear in the menu. Intent intent = new Intent();
  3. intent.setType("vnd.android.cursor.item/vnd.com.professionalandroid.provider.moonbase");
  4. intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE);
  5. // Specify flags. In this case, return all matches int flags = PackageManager.MATCH_ALL;
  6. // Generate the list
  7. List<ResolveInfo> actions; actions = packageManager.queryIntentActivities(intent, flags);
  8. // Extract the list of action names
  9. ArrayList<CharSequence> labels = new ArrayList<CharSequence>();
  10. Resources r = getResources(); for (ResolveInfo action : actions) labels.add(action.nonLocalizedLabel;

 Incorporation d'actions anonymes en tant qu'éléments de menu

 Le moyen le plus courant d’incorporer des actions d’applications tierces consiste à les inclure dans les éléments de menu de votre barre d’applications. Les menus et la barre des applications sont décrits plus en détail au chapitre 13, «Implémentation d'une expérience utilisateur Android moderne».La méthode addIntentOptions, disponible dans la classe Menu, vous permet de spécifier une intention décrivant les données utilisées dans votre activité, comme décrit précédemment. Cependant, plutôt que de simplement renvoyer une liste d’actions possibles, un nouvel élément de menu sera créé pour chacune d’elles, avec le texte renseigné à partir des étiquettes correspondant aux filtres d’intention. Pour ajouter des éléments de menu à vos menus de manière dynamique au moment de l'exécution, utilisez la méthode addIntentOptions sur l'objet Menu en question: Transmettez une intention qui spécifie les données pour lesquelles vous souhaitez fournir des actions. En règle générale, cela sera géré dans les gestionnaires onCreateOptionsMenu de vos activités ou fragments. Comme dans la section précédente, l'intention que vous créez sera utilisée pour résoudre les activités avec des filtres d'intention pouvant fournir des actions pour les données que vous spécifiez. L’intention est utilisée pour rechercher des actions, aussi ne l’attribuez pas; il ne doit spécifier que les données sur lesquelles effectuer des actions. Vous devez également spécifier la catégorie de l'action, CATEGORY_ALTERNATIVE ou CATEGORY_SELECTED_ALTERNATIVE. Le code squelette pour la création d’une intention de résolution d’action de menu est présenté ici.

  1. Intent intent = new Intent();
  2. intent.setData(MyProvider.CONTENT_URI);
  3. intent.addCategory(Intent.CATEGORY_ALTERNATIVE);

 Transmettez cette intention à addIntentOptions du menu que vous souhaitez renseigner, ainsi que tous les indicateurs d'options, le nom de la classe d'appel, le groupe de menus à utiliser et les valeurs de l'ID de menu. Vous pouvez également spécifier un tableau d'intentions que vous souhaitez utiliser pour créer des éléments de menu supplémentaires. Le Listing 6-11 donne une idée de la manière de remplir dynamiquement un menu d’activité. 

LISTING 6-11: Dynamic Menu population from advertised actions

  1. @Override
  2. public boolean onCreateOptionsMenu(Menu menu) {
  3. super.onCreateOptionsMenu(menu);
  4. // Create the intent used to resolve which actions
  5. // should appear in the menu. Intent intent = new Intent();
  6. intent.setType("vnd.android.cursor.item/vnd.com.professionalandroid.provider.moonbase");
  7. intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE);
  8. // Normal menu options to let you set a group and ID
  9. // values for the menu items you're adding.
  10. int menuGroup = 0;
  11. int menuItemId = 0;
  12. int menuItemOrder = Menu.NONE;
  13. // Provide the name of the component that's calling
  14. // the action -- generally the current Activity.
  15. ComponentName caller = getComponentName();
  16. // Define intents that should be added first.
  17. Intent[] specificIntents = null;
  18. // The menu items created from the previous Intents
  19. // will populate this array.
  20. MenuItem[] outSpecificItems = null;
  21. // Set any optional flags. int flags = Menu.FLAG_APPEND_TO_GROUP;
  22. // Populate the menu
  23. menu.addIntentOptions(menuGroup,menuItemId,menuItemOrder,caller,specificIntents,intent,flags,outSpecificItems);
  24. return true;
  25. }