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