【问题标题】:Add to menu using addIntentOptions providing multiple intents for a single activity使用 addIntentOptions 添加到菜单,为单个活动提供多个意图
【发布时间】:2010-10-07 23:33:35
【问题描述】:

我想尽可能使用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 只允许每个 Activity 有一个具有特定类别的 Intent,那么这是一个非常糟糕的限制。

我可以看到自己构建了一个虚拟活动,只需交给MyActivity。但这很笨拙,如果可能的话,我想避免它。

编辑:查看从上下文菜单(可能是选项菜单)传递给活动的意图,即使两个意图都显示在菜单中,活动也不会有足够的信息来判断选择了哪个意图,因为在活动中 getIntent().getAction() 为空。

这似乎是一个不幸的疏忽。拥有可以以多种方式使用一种类型的数据的 Activity 肯定不是很罕见吗?

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

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

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

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

【问题讨论】:

  • @SamStephens:FWIW,自 Android 1.0 以来,Google 几乎一直在退出 addIntentOptions()。这并不是说你不能使用它,但不要指望这种模式会得到很多人的喜爱。特别是,如果像您这样的奇怪情况存在错误,我至少不会感到惊讶。考虑使用queryIntentActivityOptions() 并自己填充菜单。
  • queryIntentActivityOptions() 返回的列表只会为每个匹配的 Activity 返回一个条目。
  • @CommonsWare:是否有任何关于谷歌对此的合理性的文档,或者关于我们应该做什么的任何文档。 addIntentOptions() 是设置上下文菜单的好方法。最少的代码,几乎所有的信息都是声明性的,而不是强制性的。特别是与我见过的其他上下文菜单相比,需要在多个地方进行大量代码和更改才能更改可用选项。
  • @codelark:这就是我看到的行为。这似乎很愚蠢。如果一个活动可以以多种方式使用一类数据,那么允许您指定多个意图并让活动多次匹配似乎是合乎逻辑的方式。想象一下将一个联系人的详细信息发送给另一个联系人的活动。有两种方法可以使用此活动来消费一个联系人:要么将联系人的详细信息发送给另一个联系人;要么或将其他联系人的详细信息发送给该联系人。如果没有虚拟活动或手动创建菜单,我无法在菜单中提供这两个选项
  • @SamStephens 我离开了我的开发环境,但我在下面发布了一个我认为应该可行的答案。魔力在旗帜中。如果addIntentOptions 将标志传递给queryIntentActivityOptions,那么使用值GET_INTENT_FILTERS 应该完全符合您的要求。

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


【解决方案1】:

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

对于我的工作方法,您需要为每个匹配的意图过滤器获得一个结果,这可能会导致每个活动产生多个结果。此外,您还需要获取结果中匹配的意图过滤器的信息,特别是意图过滤器的操作。

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

这种方法是有道理的,但遗憾的是它不允许 Activity 提供多种方式来使用特定 Intent。

所以我的解决方法是为具有多个操作的任何活动创建虚假活动,然后将其移交给真实活动。

所以我在问题中包含的示例清单将变为

<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 建议的那样,也可以创建自己的库,以非骇客的方式执行此操作。随着我最终获得更多应用程序,我可能会朝着这个方向前进(除非我找到我更喜欢的现有方法:-))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多