3

Je veux utiliser addIntentOptions pour piloter mes menus lorsque c'est possible. Cela semble le moyen le plus propre de les fournir. Plutôt que de détailler explicitement les activités, demandez simplement un menu répertoriant toutes les activités disponibles pour mon élément de données.Ajouter au menu en utilisant addIntentOptions fournissant plusieurs intentions pour une seule activité

Donc j'essaye de mettre en place un menu contextuel pour un ListView. Cela fonctionne très bien. Le seul problème est que j'ai une activité qui a deux intentions qui consomment mon type de données, et seulement le premier apparaît.

L'activité en question AndroidManifest.xml

<activity android:name=".ui.MyActivity" android:label="The title"> 
    <intent-filter android:label="First context label"> 
     <action android:name="com.sample.action.FIRST_ACTION" /> 
     <category android:name="android.intent.category.DEFAULT" /> 
     <category android:name="android.intent.category.ALTERNATIVE" /> 
     <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> 
     <data android:scheme="myscheme" /> 
    </intent-filter> 
    <intent-filter android:label="Second context label"> 
     <action android:name="com.sample.action.SECOND_ACTION" /> 
     <category android:name="android.intent.category.DEFAULT" /> 
     <category android:name="android.intent.category.ALTERNATIVE" /> 
     <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> 
     <data android:scheme="myscheme" /> 
    </intent-filter> 
</activity> 

Le code pour générer le menu contextuel

@Override 
public void onCreateContextMenu(ContextMenu menu, View view, 
     ContextMenuInfo menuInfo) { 
    super.onCreateContextMenu(menu, view, menuInfo); 

    Uri uri = Uri.fromParts("myscheme", getOpaqueUriOfSelectedItem(view), null) 

    Intent intent = new Intent(null, uri); 
    intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE); 

    // Search and populate the menu with acceptable offering applications. 
    menu.addIntentOptions(
      0, // Menu group to which new items will be added 
      0, // Unique item ID (none) 
      0, // Order for the items (none) 
      this.getComponentName(), // The current Activity name 
      null, // Specific items to place first (none) 
      intent, // Intent created above that describes our requirements 
      0, // Additional flags to control items (none) 
      null); // Array of MenuItems that correlate to specific items 
        // (none) 
} 

Comme je l'ai dit, la première intention de l'activité apparaît dans le menu contextuel et se comporte comme un rêve. Mais je ne vois pas la deuxième intention, et je ne vois pas pourquoi cela ne devrait pas se produire. Si Android n'autorise qu'une intention avec une catégorie particulière par activité, c'est une restriction assez boiteuse.

Je peux me voir construire une activité factice qui passe simplement à MyActivity. Mais c'est maladroit et j'aimerais l'éviter si possible. En regardant l'intention qui est passée à une activité à partir d'un menu contextuel (ou d'un menu d'options, vraisemblablement), même si les deux intentions apparaissaient dans le menu, l'activité n'aurait pas assez d'informations pour Indique quelle intention a été sélectionnée, car dans l'activité getIntent().getAction() est null.

Cela semble être un oubli malheureux. Il n'est sûrement pas inhabituel d'avoir une activité qui peut consommer un type de données de plus d'une façon? À moins que l'un de vous ne sache quelque chose que j'ai manqué, il semble que je vais créer mes activités factices.

EDIT: Comme CommonsWare suggéré, j'ai essayé d'utiliser queryIntentActivityOptions. J'ai ajouté dans ce code avant menu.addIntentOptions dans mon code ci-dessus.

PackageManager pm = getPackageManager(); 
final List<ResolveInfo> available = 
    pm.queryIntentActivityOptions(this.getComponentName(), null, intent, 0); 

Et dans le débogueur, je trouve que available ne comprenait pas les deux intentions disponibles pour MyActivity. Donc, le problème ne se trouve pas dans addIntentOptions, c'est plus profond, dans queryIntentActivityOptions quelque part.

+1

@SamStephens: FWIW, Google a été backpedaling de 'addIntentOptions()' à peu près depuis Android 1.0. Cela ne veut pas dire que vous ne pouvez pas l'utiliser, mais ne vous attendez pas à ce que ce modèle devienne un véritable amour pour l'avenir. En particulier, cela ne me surprendrait pas du tout s'il y a des bugs pour des cas bizarres comme le vôtre. Pensez à utiliser 'queryIntentActivityOptions()' et à remplir le menu vous-même. – CommonsWare

+0

La liste que 'queryIntentActivityOptions()' renvoie ne retournera qu'une seule entrée pour chaque activité correspondante. – codelark

+0

@CommonsWare: Existe-t-il une documentation de la raison d'être de Google pour cette disponibilité, ou quoi que ce soit à propos de ce que nous sommes censés faire à la place. 'addIntentOptions()' est un excellent moyen de configurer un menu contextuel. Une quantité minimale de code, et presque toutes les informations déclaratives, pas impératives. Particulièrement par rapport aux autres menus contextuels que j'ai vus, avec des règles de code et des changements requis dans plusieurs endroits pour changer les options disponibles. – SamStephens

Répondre

2

Mon approche ne peut pas fonctionner parce que queryIntentActivityOptions(), et les méthodes qui l'appellent, ne fonctionnent pas de la manière requise pour mon approche.

Pour mon approche de travail, vous devez obtenir un résultat par match-filtre correspondant, ce qui peut entraîner plusieurs résultats par activité. En outre, vous devez obtenir des informations sur le filtre d'intention correspondant au résultat, en particulier l'action du filtre d'intention.

Cependant queryIntentActivityOptions() ne trouve pas -filtres intention, il trouve activités avec au moins un filtre correspondant intention. Cela signifie que vous obtenez seulement un résultat par activité. Le résultat ne fournit également aucune information sur le filtre d'intention correspondant à votre intention.

Cette approche est logique, mais il est dommage qu'elle ne permette pas à une activité de fournir plusieurs façons de consommer une intention particulière. Donc, ma solution consiste à créer de fausses activités pour toute activité avec plus d'une action, puis passer à l'activité réelle.

Ainsi, le manifeste d'exemple que j'inclus dans la question deviendrait

<activity android:name=".ui.MyActivity" android:label="The title" /> 
<activity android:name=".ui.MyActivityFirstAction" android:label="First action"> 
    <intent-filter android:label="First context label"> 
     <action android:name="com.sample.action.FIRST_ACTION" /> 
     <category android:name="android.intent.category.DEFAULT" /> 
     <category android:name="android.intent.category.ALTERNATIVE" /> 
     <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> 
     <data android:scheme="myscheme" /> 
    </intent-filter> 
</activity> 
<activity android:name=".ui.MyActivitySecondAction" android:label="Second action"> 
    <intent-filter android:label="Second context label"> 
     <action android:name="com.sample.action.SECOND_ACTION" /> 
     <category android:name="android.intent.category.DEFAULT" /> 
     <category android:name="android.intent.category.ALTERNATIVE" /> 
     <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> 
     <data android:scheme="myscheme" /> 
    </intent-filter> 
</activity> 

MyActivityFirstAction et MyActivitySecondAction serait simplement appeler MyActivity avec les mesures appropriées et les données.

Je n'aime pas beaucoup ce schéma, mais il conserve toutes les actions qui sont dans les menus contextuels définis dans les données XML plutôt que dans le code, et me permet d'utiliser addIntentOptions(). Je considère toujours addIntentOptions() très bien rangé, et même si CommonTasks me dit que Google a été backpedaling de celui-ci, je vais continuer à l'utiliser jusqu'à ce que je rencontre des problèmes.

EDIT: Comme CommonsWare le suggère, il serait également possible de créer votre propre bibliothèque pour le faire de manière non-hackish. Comme je me retrouve avec plus d'applications, je vais probablement aller dans cette direction (sauf si je trouve une méthode existante que j'aime mieux :-)).

Questions connexes