Я хочу отобразить список действий, который отображает все приложения, которые могут просмотреть и/или ИЗМЕНИТЬ некоторые данные. Есть ли простой способ сделать это, или мне нужно реализовать свой собственный диалог выбора действий? Или, может быть, я могу просто подкласс 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, оно будет отображаться дважды в списке, один из которых откроет файл для просмотра, а другой для редактирования, и вы не обязательно будете знать, что именно. Я думаю, что для полного решения потребуется настраиваемый выбор приложений, как предложил Тим.
EDIT (полное решение!):
Я нашел решение, которое не связано с написанием пользовательского выбора. Чтобы отличать приложения ACTION_EDIT от приложений ACTION_VIEW, я нашел способ добавить строку "(для редактирования)" к ярлыкам для одного из них (в моем случае ACTION_EDIT), используя строку кода Tim. Кроме того, чтобы убедиться, что добавленная строка не является частью имени приложения, я изменил ее цвет на голубой:
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).
Ответ 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"));
Обязательно настройте свой тип правильно, чтобы приложения знали, что вы хотите открыть что-то, с чем они могут справиться.
EDIT: Я думаю, вам нужно будет использовать запрос диспетчера пакетов, чтобы получить ваши два списка, а затем объединить их в один и сделать свое собственное действие/диалог, который будет всплывать и заполняться данные, содержащиеся в вашем объединенном списке.
Вот пример, делающий запрос:
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(intent, 0);
поэтому, если вы сделаете два своих намерения и дважды назовете это, передав каждое намерение, вы сможете объединить полученные списки, чтобы получить полный набор возможностей. Затем нужно создать для него активность или диалог.