/* 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 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 getItems(final Context context, Intent[] intents) { final ArrayList items = new ArrayList(); // 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 getItems(final Context context, final GeckoActionProvider provider) { final ArrayList items = new ArrayList(); // Add any intents from the provider. final PackageManager packageManager = context.getPackageManager(); final ArrayList 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 getItemsForIntent(Context context, Intent intent) { ArrayList items = new ArrayList(); PackageManager pm = context.getPackageManager(); List 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; } }