【问题标题】:How to make an intent with multiple actions如何通过多个动作制定意图
【发布时间】:2012-06-13 18:23:04
【问题描述】:

我想显示一个活动选择器,显示所有可以查看和/或编辑某些数据的应用程序。有没有一种简单的方法可以做到这一点,还是我必须实现自己的活动选择器对话框?或者我可以只继承Intent?谢谢。

【问题讨论】:

标签: android android-intent


【解决方案1】:

我通过使用 EXTRA_INITIAL_INTENTS 找到了部分解决方案:

Intent viewIntent = new Intent(Intent.ACTION_VIEW);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
viewIntent.setDataAndType(uri, type);
editIntent.setDataAndType(uri, type);
Intent chooserIntent = Intent.createChooser(editIntent, "Open in...");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { viewIntent });
startActivity(chooserIntent);

我说部分是因为如果应用同时支持 ACTION_VIEW 和 ACTION_EDIT,它将在列表中显示两次,其中一个将打开文件进行查看,另一个将打开文件进行编辑,您不一定知道哪个是哪个。正如 Tim 建议的那样,我认为一个完整的解决方案需要一个自定义应用选择器。

编辑(完整解决方案!):

我找到了一个不涉及编写自定义应用选择器的解决方案。为了将 ACTION_EDIT 应用程序与 ACTION_VIEW 应用程序区分开来,我找到了一种方法,通过使用 Tim 提供的代码行,将“(用于编辑)”字符串附加到其中一个(在我的情况下为 ACTION_EDIT)的标签上。此外,为了确保附加的字符串看起来不是应用名称的一部分,我将其颜色更改为青色:

PackageManager pm = kyoPrint.getPackageManager();
Intent viewIntent = new Intent(Intent.ACTION_VIEW);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
viewIntent.setDataAndType(uri, type);
editIntent.setDataAndType(uri, type);
Intent openInChooser = Intent.createChooser(viewIntent, "Open in...");

// Append " (for editing)" to applicable apps, otherwise they will show up twice identically
Spannable forEditing = new SpannableString(" (for editing)");
forEditing.setSpan(new ForegroundColorSpan(Color.CYAN), 0, forEditing.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
List<ResolveInfo> resInfo = pm.queryIntentActivities(editIntent, 0);
Intent[] extraIntents = new Intent[resInfo.size()];
for (int i = 0; i < resInfo.size(); i++) {
    // Extract the label, append it, and repackage it in a LabeledIntent
    ResolveInfo ri = resInfo.get(i);
    String packageName = ri.activityInfo.packageName;
    Intent intent = new Intent();
    intent.setComponent(new ComponentName(packageName, ri.activityInfo.name));
    intent.setAction(Intent.ACTION_EDIT);
    intent.setDataAndType(uri, type);
    CharSequence label = TextUtils.concat(ri.loadLabel(pm), forEditing);
    extraIntents[i] = new LabeledIntent(intent, packageName, label, ri.icon);
}

openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
startActivity(openInChooser);

编辑 2:错误

如果第一个意图没有找到任何活动,则不会显示任何活动,包括第二个意图找到的任何活动。我最终编写了自己的选择器。我刚刚填充了一个 ExpandableListView,其中包含每种意图类型的标题以及它们各自作为子项的活动(存储为单独的 LabeledIntents)。

【讨论】:

  • 很好的答案!我想用来自几种不同类型的 Intent 甚至是应用内 Activity 做一个选择器,这让我可以将它们全部合并到一个选择器中。
  • 这太棒了!!我想使用我发现的所有不同意图启动尽可能多的浏览器来查看本地 HTML 文件。这很好用,谢谢。
  • @Ken 是否可以避免选择器中的重复项目?我说的是存在于一个意图和另一个意图中的项目?我正在尝试创建一个共享选择器,并希望将消息设置为 SMS 短消息,但我不知道该怎么做。
  • 可以,通过PackageManager.queryIntentActivities()获取每个Intent的ResolveInfo后,可以通过ResolveInfo.activityInfo.packageName比较它们的包名,过滤掉重复项。
  • @Ken 我明白了。是否也可以隐藏我不想显示的项目?
【解决方案2】:

取决于您的数据是什么。但通常使用 ACTION_VIEW 并附加一些数据,您可以使用 IntentChoooser 向用户填充选项列表。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "some data");  
startActivity(Intent.createChooser(intent, "Open with"));

请务必正确设置您的类型,以便应用程序知道您要打开它们可能能够处理的内容。

编辑:我认为您必须使用包管理器查询来获取您的两个列表,然后将它们合并为一个并制作您自己的活动/对话框,该活动/对话框将弹出并填充合并列表中包含的数据。

这是一个查询示例:

List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(intent, 0);

因此,如果您创建两个 Intent 并调用它两次,传入每个 Intent,您应该能够组合结果列表以获得您的全部可能性。然后是创建一个活动或对话框来显示它们。

【讨论】:

  • 我想显示所有支持 ACTION_VIEW ACTION_EDIT的应用,而不仅仅是 ACTION_VIEW
  • 啊,我明白了。我认为你必须自己做更多的跑腿工作。查看我的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-04
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多