1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.prompts;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.widget.GeckoActionProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.widget.ListView;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
* Shows a prompt letting the user pick from a list of intent handlers for a set of Intents or
* for a GeckoActionProvider. Basic usage:
* IntentChooserPrompt prompt = new IntentChooserPrompt(context, new Intent[] {
* ... // some intents
* });
* prompt.show("Title", context, new IntentHandler() {
* public void onIntentSelected(Intent intent, int position) { }
* public void onCancelled() { }
* });
**/
public class IntentChooserPrompt {
private static final String LOGTAG = "GeckoIntentChooser";
private final ArrayList<PromptListItem> mItems;
public IntentChooserPrompt(Context context, Intent[] intents) {
mItems = getItems(context, intents);
}
public IntentChooserPrompt(Context context, GeckoActionProvider provider) {
mItems = getItems(context, provider);
}
/* If an IntentHandler is passed in, will asynchronously call the handler when the dialog is closed
* Otherwise, will return the Intent that was chosen by the user. Must be called on the UI thread.
*/
public void show(final String title, final Context context, final IntentHandler handler) {
ThreadUtils.assertOnUiThread();
if (mItems.isEmpty()) {
Log.i(LOGTAG, "No activities for the intent chooser!");
handler.onCancelled();
return;
}
// If there's only one item in the intent list, just return it
if (mItems.size() == 1) {
handler.onIntentSelected(mItems.get(0).getIntent(), 0);
return;
}
final Prompt prompt = new Prompt(context, new Prompt.PromptCallback() {
@Override
public void onPromptFinished(String promptServiceResult) {
if (handler == null) {
return;
}
int itemId = -1;
try {
itemId = new JSONObject(promptServiceResult).getInt("button");
} catch (JSONException e) {
Log.e(LOGTAG, "result from promptservice was invalid: ", e);
}
if (itemId == -1) {
handler.onCancelled();
} else {
handler.onIntentSelected(mItems.get(itemId).getIntent(), itemId);
}
}
});
PromptListItem[] arrays = new PromptListItem[mItems.size()];
mItems.toArray(arrays);
prompt.show(title, "", arrays, ListView.CHOICE_MODE_NONE);
return;
}
// Whether or not any activities were found. Useful for checking if you should try a different Intent set
public boolean hasActivities(Context context) {
return mItems.isEmpty();
}
// Gets a list of PromptListItems for an Intent array
private ArrayList<PromptListItem> getItems(final Context context, Intent[] intents) {
final ArrayList<PromptListItem> items = new ArrayList<PromptListItem>();
// If we have intents, use them to build the initial list
for (final Intent intent : intents) {
items.addAll(getItemsForIntent(context, intent));
}
return items;
}
// Gets a list of PromptListItems for a GeckoActionProvider
private ArrayList<PromptListItem> getItems(final Context context, final GeckoActionProvider provider) {
final ArrayList<PromptListItem> items = new ArrayList<PromptListItem>();
// Add any intents from the provider.
final PackageManager packageManager = context.getPackageManager();
final ArrayList<ResolveInfo> infos = provider.getSortedActivities();
for (final ResolveInfo info : infos) {
items.add(getItemForResolveInfo(info, packageManager, provider.getIntent()));
}
return items;
}
private PromptListItem getItemForResolveInfo(ResolveInfo info, PackageManager pm, Intent intent) {
PromptListItem item = new PromptListItem(info.loadLabel(pm).toString());
item.setIcon(info.loadIcon(pm));
Intent i = new Intent(intent);
// These intents should be implicit.
i.setComponent(new ComponentName(info.activityInfo.applicationInfo.packageName,
info.activityInfo.name));
item.setIntent(new Intent(i));
return item;
}
private ArrayList<PromptListItem> getItemsForIntent(Context context, Intent intent) {
ArrayList<PromptListItem> items = new ArrayList<PromptListItem>();
PackageManager pm = context.getPackageManager();
List<ResolveInfo> lri = pm.queryIntentActivityOptions(GeckoAppShell.getGeckoInterface().getActivity().getComponentName(), null, intent, 0);
// If we didn't find any activities, just return the empty list
if (lri == null) {
return items;
}
// Otherwise, convert the ResolveInfo. Note we don't currently check for duplicates here.
for (ResolveInfo ri : lri) {
items.add(getItemForResolveInfo(ri, pm, intent));
}
return items;
}
}
|