使用addIntentOptions添加到菜单,为单个活动提供多个意图

时间:2010-10-07 23:33:36

标签: java android android-intent android-manifest intentfilter

我想尽可能使用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()为空。

这似乎是一次不幸的疏忽。当然,拥有一种能够以多种方式消耗某种数据的活动并不罕见吗?

除非你们其中一个善良的人知道我错过了什么,否则看起来我将要创建我的虚拟活动。

编辑:正如CommonsWare建议的那样,我尝试使用queryIntentActivityOptions。我在上面的代码中在menu.addIntentOptions之前添加了此代码。

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

在调试器中,我发现available没有包含MyActivity的两个可用意图。所以问题不在addIntentOptions范围内,而是在queryIntentActivityOptions某处更深处。

1 个答案:

答案 0 :(得分:2)

我的方法不起作用,因为queryIntentActivityOptions()以及调用它的方法不能以我的方法所需的方式工作。

对于我的工作方法,您需要根据匹配的intent-filter获得结果,这可能会导致每个活动产生多个结果。此外,您需要获取有关结果中匹配哪个intent-filter的信息,特别是intent-filter的操作。

但是queryIntentActivityOptions()找不到 intent-filters ,它会找到至少有一个匹配的intent-filter的活动。这意味着每个活动只能获得一个结果。结果还没有提供与您的意图相匹配的意图过滤器的信息。

这种方法很有意义,但令人遗憾的是它不允许活动提供多种方式来消费特定的意图。

因此,我的解决方法是为具有多个操作的任何活动创建虚假活动,然后切换到真实活动。

因此,问题中包含的样本清单将成为

<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告诉我谷歌一直在退缩,我也会继续使用它,直到遇到问题为止。

编辑:正如CommonsWare建议的那样,也可以创建自己的库,以非黑客的方式做到这一点。当我最终得到更多的应用程序时,我可能会朝着这个方向前进(除非我找到一个我更喜欢的现有方法:-))。