如何使用多个操作制作意图

时间:2012-06-13 18:23:04

标签: android android-intent

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

2 个答案:

答案 0 :(得分:59)

我使用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,它将在列表中显示两次,其中一个将打开文件进行查看而另一个用于编辑,你不一定知道哪个是哪个。我认为一个完整的解决方案需要一个自定义应用程序选择器,正如蒂姆建议的那样。

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

我找到了一个不涉及编写自定义应用选择器的解决方案。为了区分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);

enter image description here

编辑2:BUG

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

答案 1 :(得分:4)

取决于您的数据。但是通常使用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并将其调用两次,传递每个意图,您应该能够组合结果列表以获得全部可能性。然后,可以创建一个活动或对话框来显示它们。