36

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

4

2 回答 2

68

我通过使用 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:错误

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

于 2012-06-14T17:31:53.630 回答
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 并调用它两次,传入每个 Intent,您应该能够组合结果列表以获得您的全部可能性。然后是创建一个活动或对话框来显示它们。

于 2012-06-13T18:30:54.667 回答