mobile/android/base/FilePicker.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 package org.mozilla.gecko;
michael@0 6
michael@0 7 import org.mozilla.gecko.GeckoAppShell;
michael@0 8 import org.mozilla.gecko.util.ThreadUtils;
michael@0 9 import org.mozilla.gecko.util.GeckoEventListener;
michael@0 10
michael@0 11 import org.json.JSONException;
michael@0 12 import org.json.JSONObject;
michael@0 13
michael@0 14 import android.app.Activity;
michael@0 15 import android.content.ComponentName;
michael@0 16 import android.content.Context;
michael@0 17 import android.content.Intent;
michael@0 18 import android.content.pm.PackageManager;
michael@0 19 import android.content.pm.ResolveInfo;
michael@0 20 import android.net.Uri;
michael@0 21 import android.os.Environment;
michael@0 22 import android.os.Parcelable;
michael@0 23 import android.provider.MediaStore;
michael@0 24 import android.util.Log;
michael@0 25
michael@0 26 import java.io.File;
michael@0 27 import java.util.ArrayList;
michael@0 28 import java.util.Collection;
michael@0 29 import java.util.HashMap;
michael@0 30 import java.util.Iterator;
michael@0 31 import java.util.List;
michael@0 32
michael@0 33 public class FilePicker implements GeckoEventListener {
michael@0 34 private static final String LOGTAG = "GeckoFilePicker";
michael@0 35 private static FilePicker sFilePicker;
michael@0 36 private final Context context;
michael@0 37
michael@0 38 public interface ResultHandler {
michael@0 39 public void gotFile(String filename);
michael@0 40 }
michael@0 41
michael@0 42 public static void init(Context context) {
michael@0 43 if (sFilePicker == null) {
michael@0 44 sFilePicker = new FilePicker(context.getApplicationContext());
michael@0 45 }
michael@0 46 }
michael@0 47
michael@0 48 protected FilePicker(Context context) {
michael@0 49 this.context = context;
michael@0 50 GeckoAppShell.getEventDispatcher().registerEventListener("FilePicker:Show", this);
michael@0 51 }
michael@0 52
michael@0 53 @Override
michael@0 54 public void handleMessage(String event, final JSONObject message) {
michael@0 55 if (event.equals("FilePicker:Show")) {
michael@0 56 String mimeType = "*/*";
michael@0 57 final String mode = message.optString("mode");
michael@0 58 final int tabId = message.optInt("tabId", -1);
michael@0 59
michael@0 60 if ("mimeType".equals(mode))
michael@0 61 mimeType = message.optString("mimeType");
michael@0 62 else if ("extension".equals(mode))
michael@0 63 mimeType = GeckoAppShell.getMimeTypeFromExtensions(message.optString("extensions"));
michael@0 64
michael@0 65 showFilePickerAsync(mimeType, new ResultHandler() {
michael@0 66 public void gotFile(String filename) {
michael@0 67 try {
michael@0 68 message.put("file", filename);
michael@0 69 } catch (JSONException ex) {
michael@0 70 Log.i(LOGTAG, "Can't add filename to message " + filename);
michael@0 71 }
michael@0 72
michael@0 73
michael@0 74 GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
michael@0 75 "FilePicker:Result", message.toString()));
michael@0 76 }
michael@0 77 }, tabId);
michael@0 78 }
michael@0 79 }
michael@0 80
michael@0 81 private void addActivities(Intent intent, HashMap<String, Intent> intents, HashMap<String, Intent> filters) {
michael@0 82 PackageManager pm = context.getPackageManager();
michael@0 83 List<ResolveInfo> lri = pm.queryIntentActivities(intent, 0);
michael@0 84 for (ResolveInfo ri : lri) {
michael@0 85 ComponentName cn = new ComponentName(ri.activityInfo.applicationInfo.packageName, ri.activityInfo.name);
michael@0 86 if (filters != null && !filters.containsKey(cn.toString())) {
michael@0 87 Intent rintent = new Intent(intent);
michael@0 88 rintent.setComponent(cn);
michael@0 89 intents.put(cn.toString(), rintent);
michael@0 90 }
michael@0 91 }
michael@0 92 }
michael@0 93
michael@0 94 private Intent getIntent(String mimeType) {
michael@0 95 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
michael@0 96 intent.setType(mimeType);
michael@0 97 intent.addCategory(Intent.CATEGORY_OPENABLE);
michael@0 98 return intent;
michael@0 99 }
michael@0 100
michael@0 101 private List<Intent> getIntentsForFilePicker(final String mimeType,
michael@0 102 final FilePickerResultHandler fileHandler) {
michael@0 103 // The base intent to use for the file picker. Even if this is an implicit intent, Android will
michael@0 104 // still show a list of Activitiees that match this action/type.
michael@0 105 Intent baseIntent;
michael@0 106 // A HashMap of Activities the base intent will show in the chooser. This is used
michael@0 107 // to filter activities from other intents so that we don't show duplicates.
michael@0 108 HashMap<String, Intent> baseIntents = new HashMap<String, Intent>();
michael@0 109 // A list of other activities to shwo in the picker (and the intents to launch them).
michael@0 110 HashMap<String, Intent> intents = new HashMap<String, Intent> ();
michael@0 111
michael@0 112 if ("audio/*".equals(mimeType)) {
michael@0 113 // For audio the only intent is the mimetype
michael@0 114 baseIntent = getIntent(mimeType);
michael@0 115 addActivities(baseIntent, baseIntents, null);
michael@0 116 } else if ("image/*".equals(mimeType)) {
michael@0 117 // For images the base is a capture intent
michael@0 118 baseIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
michael@0 119 baseIntent.putExtra(MediaStore.EXTRA_OUTPUT,
michael@0 120 Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
michael@0 121 fileHandler.generateImageName())));
michael@0 122 addActivities(baseIntent, baseIntents, null);
michael@0 123
michael@0 124 // We also add the mimetype intent
michael@0 125 addActivities(getIntent(mimeType), intents, baseIntents);
michael@0 126 } else if ("video/*".equals(mimeType)) {
michael@0 127 // For videos the base is a capture intent
michael@0 128 baseIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
michael@0 129 addActivities(baseIntent, baseIntents, null);
michael@0 130
michael@0 131 // We also add the mimetype intent
michael@0 132 addActivities(getIntent(mimeType), intents, baseIntents);
michael@0 133 } else {
michael@0 134 baseIntent = getIntent("*/*");
michael@0 135 addActivities(baseIntent, baseIntents, null);
michael@0 136
michael@0 137 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
michael@0 138 intent.putExtra(MediaStore.EXTRA_OUTPUT,
michael@0 139 Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
michael@0 140 fileHandler.generateImageName())));
michael@0 141 addActivities(intent, intents, baseIntents);
michael@0 142 intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
michael@0 143 addActivities(intent, intents, baseIntents);
michael@0 144 }
michael@0 145
michael@0 146 // If we didn't find any activities, we fall back to the */* mimetype intent
michael@0 147 if (baseIntents.size() == 0 && intents.size() == 0) {
michael@0 148 intents.clear();
michael@0 149
michael@0 150 baseIntent = getIntent("*/*");
michael@0 151 addActivities(baseIntent, baseIntents, null);
michael@0 152 }
michael@0 153
michael@0 154 ArrayList<Intent> vals = new ArrayList<Intent>(intents.values());
michael@0 155 vals.add(0, baseIntent);
michael@0 156 return vals;
michael@0 157 }
michael@0 158
michael@0 159 private String getFilePickerTitle(String mimeType) {
michael@0 160 if (mimeType.equals("audio/*")) {
michael@0 161 return context.getString(R.string.filepicker_audio_title);
michael@0 162 } else if (mimeType.equals("image/*")) {
michael@0 163 return context.getString(R.string.filepicker_image_title);
michael@0 164 } else if (mimeType.equals("video/*")) {
michael@0 165 return context.getString(R.string.filepicker_video_title);
michael@0 166 } else {
michael@0 167 return context.getString(R.string.filepicker_title);
michael@0 168 }
michael@0 169 }
michael@0 170
michael@0 171 private interface IntentHandler {
michael@0 172 public void gotIntent(Intent intent);
michael@0 173 }
michael@0 174
michael@0 175 /* Gets an intent that can open a particular mimetype. Will show a prompt with a list
michael@0 176 * of Activities that can handle the mietype. Asynchronously calls the handler when
michael@0 177 * one of the intents is selected. If the caller passes in null for the handler, will still
michael@0 178 * prompt for the activity, but will throw away the result.
michael@0 179 */
michael@0 180 private void getFilePickerIntentAsync(final String mimeType,
michael@0 181 final FilePickerResultHandler fileHandler,
michael@0 182 final IntentHandler handler) {
michael@0 183 List<Intent> intents = getIntentsForFilePicker(mimeType, fileHandler);
michael@0 184
michael@0 185 if (intents.size() == 0) {
michael@0 186 Log.i(LOGTAG, "no activities for the file picker!");
michael@0 187 handler.gotIntent(null);
michael@0 188 return;
michael@0 189 }
michael@0 190
michael@0 191 Intent base = intents.remove(0);
michael@0 192
michael@0 193 if (intents.size() == 0) {
michael@0 194 handler.gotIntent(base);
michael@0 195 return;
michael@0 196 }
michael@0 197
michael@0 198 Intent chooser = Intent.createChooser(base, getFilePickerTitle(mimeType));
michael@0 199 chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[]{}));
michael@0 200 handler.gotIntent(chooser);
michael@0 201 }
michael@0 202
michael@0 203 /* Allows the user to pick an activity to load files from using a list prompt. Then opens the activity and
michael@0 204 * sends the file returned to the passed in handler. If a null handler is passed in, will still
michael@0 205 * pick and launch the file picker, but will throw away the result.
michael@0 206 */
michael@0 207 protected void showFilePickerAsync(String mimeType, final ResultHandler handler, final int tabId) {
michael@0 208 final FilePickerResultHandler fileHandler = new FilePickerResultHandler(handler, context, tabId);
michael@0 209 getFilePickerIntentAsync(mimeType, fileHandler, new IntentHandler() {
michael@0 210 @Override
michael@0 211 public void gotIntent(Intent intent) {
michael@0 212 if (handler == null) {
michael@0 213 return;
michael@0 214 }
michael@0 215
michael@0 216 if (intent == null) {
michael@0 217 handler.gotFile("");
michael@0 218 return;
michael@0 219 }
michael@0 220
michael@0 221 ActivityHandlerHelper.startIntent(intent, fileHandler);
michael@0 222 }
michael@0 223 });
michael@0 224 }
michael@0 225 }

mercurial