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.

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

mercurial