Добавить в меню, используя addIntentOptions, предоставляя несколько намерений для одного действия - PullRequest
3 голосов
/ 08 октября 2010

Я хочу использовать addIntentOptions для управления моими меню, когда это возможно. Это кажется самым чистым способом обеспечить их. Вместо того, чтобы подробно описывать действия, просто попросите меню со списком всех действий, которые доступны для моего элемента данных.

Итак, я пытаюсь собрать контекстное меню для ListView. Работает отлично. Единственная проблема заключается в том, что у меня есть действие с двумя намерениями, которые используют мой тип данных, и отображается только первое.

Активность, о которой идет речь в 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> 

Код для генерации контекстного меню

@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)
}

Как я уже сказал, первый смысл действия отображается в контекстном меню и ведет себя как сон. Но я не вижу второго намерения и не вижу веской причины, по которой оно не должно появиться. Если Android допускает только одно намерение с определенной категорией для каждого вида деятельности, это довольно слабое ограничение.

Я вижу, как я создаю фиктивную деятельность, которая просто переходит на MyActivity. Но это неуклюже, и я хотел бы избежать этого, если это возможно.

РЕДАКТИРОВАТЬ : Если посмотреть на намерение, которое передается действию из контекстного меню (или, предположительно, меню параметров), даже если оба намерения отображаются в меню, действие не будет достаточно информации, чтобы сказать, какое намерение было выбрано, так как в действии getIntent().getAction() пусто.

Это похоже на неудачный недосмотр. Конечно, не так уж необычно иметь деятельность, которая может потреблять тип данных более чем одним способом?

Если один из вас, добрые люди, не знает что-то, что я пропустил, похоже, что я собираюсь создавать свои фиктивные действия.

EDIT : Как и предполагал CommonsWare, я попытался использовать queryIntentActivityOptions. Я добавил в этот код до menu.addIntentOptions в моем коде выше.

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

И в отладчике я обнаружил, что available не включает оба доступных намерения для MyActivity. Так что проблема не в addIntentOptions, она глубже, в queryIntentActivityOptions где-то.

1 Ответ

2 голосов
/ 11 октября 2010

Мой подход не может работать, потому что queryIntentActivityOptions() и методы, которые его вызывают, не работают так, как требуется для моего подхода.

Для моего подхода к работе вам необходимо получить результатв соответствии с фильтром намерений, что может привести к нескольким результатам на одно действие.Кроме того, вам необходимо получить информацию о том, какой фильтр намерений совпал в результате, в частности, о действии фильтра намерений.

Однако queryIntentActivityOptions() не находит фильтры намерений он находит действий по крайней мере с одним подходящим фильтром намерений.Это означает, что вы получаете только один результат за действие.Результат также не дает никакой информации о фильтре намерений, который соответствует вашему намерению.

Этот подход имеет смысл, но обидно, что он не позволяет какой-либо деятельности предоставить несколько способов использования определенного намерения.

Итак, мой обходной путь - создать поддельные действия для любого действия с более чем одним действием, которое затем передается реальной деятельности.

Таким образом, образец манифеста, который я включил в вопрос, станет

<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 и MyActivitySecondAction просто вызвали бы MyActivity с соответствующим действием и данными.

Мне не очень нравится эта схема, но она по-прежнему сохраняет все действия в контекстеменю, определенные в данных XML, а не в коде, и позволяют мне использовать addIntentOptions().

Я все еще считаю addIntentOptions() очень аккуратным, и даже если CommonTasks скажет мне, что Google отступил от него, я будупродолжайте использовать это, пока я не сталкиваюсь с проблемами.

РЕДАКТИРОВАТЬ : Как CommonsWare suБоже, можно было бы создать свою собственную библиотеку, чтобы сделать это не хакерским способом.Поскольку у меня будет больше приложений, я, вероятно, буду двигаться в этом направлении (если я не найду существующий метод, который мне нравится больше :-)).

...