| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.ui.base; | 5 package org.chromium.ui.base; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.app.Activity; | 8 import android.app.Activity; |
| 9 import android.content.ClipData; | 9 import android.content.ClipData; |
| 10 import android.content.ContentResolver; | 10 import android.content.ContentResolver; |
| 11 import android.content.Context; |
| 11 import android.content.Intent; | 12 import android.content.Intent; |
| 12 import android.net.Uri; | 13 import android.net.Uri; |
| 13 import android.os.AsyncTask; | 14 import android.os.AsyncTask; |
| 14 import android.os.Build; | 15 import android.os.Build; |
| 15 import android.os.Environment; | |
| 16 import android.provider.MediaStore; | 16 import android.provider.MediaStore; |
| 17 import android.text.TextUtils; | 17 import android.text.TextUtils; |
| 18 import android.util.Log; |
| 18 | 19 |
| 19 import org.chromium.base.CalledByNative; | 20 import org.chromium.base.CalledByNative; |
| 20 import org.chromium.base.ContentUriUtils; | 21 import org.chromium.base.ContentUriUtils; |
| 21 import org.chromium.base.JNINamespace; | 22 import org.chromium.base.JNINamespace; |
| 22 import org.chromium.ui.R; | 23 import org.chromium.ui.R; |
| 23 | 24 |
| 24 import java.io.File; | 25 import java.io.File; |
| 26 import java.io.IOException; |
| 25 import java.util.ArrayList; | 27 import java.util.ArrayList; |
| 26 import java.util.Arrays; | 28 import java.util.Arrays; |
| 27 import java.util.List; | 29 import java.util.List; |
| 28 | 30 |
| 29 /** | 31 /** |
| 30 * A dialog that is triggered from a file input field that allows a user to sele
ct a file based on | 32 * A dialog that is triggered from a file input field that allows a user to sele
ct a file based on |
| 31 * a set of accepted file types. The path of the selected file is passed to the
native dialog. | 33 * a set of accepted file types. The path of the selected file is passed to the
native dialog. |
| 32 */ | 34 */ |
| 33 @JNINamespace("ui") | 35 @JNINamespace("ui") |
| 34 class SelectFileDialog implements WindowAndroid.IntentCallback{ | 36 class SelectFileDialog implements WindowAndroid.IntentCallback{ |
| 37 private static final String TAG = "SelectFileDialog"; |
| 35 private static final String IMAGE_TYPE = "image/"; | 38 private static final String IMAGE_TYPE = "image/"; |
| 36 private static final String VIDEO_TYPE = "video/"; | 39 private static final String VIDEO_TYPE = "video/"; |
| 37 private static final String AUDIO_TYPE = "audio/"; | 40 private static final String AUDIO_TYPE = "audio/"; |
| 38 private static final String ALL_IMAGE_TYPES = IMAGE_TYPE + "*"; | 41 private static final String ALL_IMAGE_TYPES = IMAGE_TYPE + "*"; |
| 39 private static final String ALL_VIDEO_TYPES = VIDEO_TYPE + "*"; | 42 private static final String ALL_VIDEO_TYPES = VIDEO_TYPE + "*"; |
| 40 private static final String ALL_AUDIO_TYPES = AUDIO_TYPE + "*"; | 43 private static final String ALL_AUDIO_TYPES = AUDIO_TYPE + "*"; |
| 41 private static final String ANY_TYPES = "*/*"; | 44 private static final String ANY_TYPES = "*/*"; |
| 42 private static final String CAPTURE_IMAGE_DIRECTORY = "browser-photos"; | 45 private static final String CAPTURE_IMAGE_DIRECTORY = "browser-photos"; |
| 46 // Keep this variable in sync with the value defined in file_paths.xml. |
| 47 private static final String IMAGE_FILE_PATH = "images"; |
| 43 | 48 |
| 44 private final long mNativeSelectFileDialog; | 49 private final long mNativeSelectFileDialog; |
| 45 private List<String> mFileTypes; | 50 private List<String> mFileTypes; |
| 46 private boolean mCapture; | 51 private boolean mCapture; |
| 47 private Uri mCameraOutputUri; | 52 private Uri mCameraOutputUri; |
| 48 | 53 |
| 49 private SelectFileDialog(long nativeSelectFileDialog) { | 54 private SelectFileDialog(long nativeSelectFileDialog) { |
| 50 mNativeSelectFileDialog = nativeSelectFileDialog; | 55 mNativeSelectFileDialog = nativeSelectFileDialog; |
| 51 } | 56 } |
| 52 | 57 |
| 53 /** | 58 /** |
| 54 * Creates and starts an intent based on the passed fileTypes and capture va
lue. | 59 * Creates and starts an intent based on the passed fileTypes and capture va
lue. |
| 55 * @param fileTypes MIME types requested (i.e. "image/*") | 60 * @param fileTypes MIME types requested (i.e. "image/*") |
| 56 * @param capture The capture value as described in http://www.w3.org/TR/htm
l-media-capture/ | 61 * @param capture The capture value as described in http://www.w3.org/TR/htm
l-media-capture/ |
| 57 * @param multiple Whether it should be possible to select multiple files. | 62 * @param multiple Whether it should be possible to select multiple files. |
| 58 * @param window The WindowAndroid that can show intents | 63 * @param window The WindowAndroid that can show intents |
| 59 */ | 64 */ |
| 60 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) | 65 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) |
| 61 @CalledByNative | 66 @CalledByNative |
| 62 private void selectFile( | 67 private void selectFile( |
| 63 String[] fileTypes, boolean capture, boolean multiple, WindowAndroid
window) { | 68 String[] fileTypes, boolean capture, boolean multiple, WindowAndroid
window) { |
| 64 mFileTypes = new ArrayList<String>(Arrays.asList(fileTypes)); | 69 mFileTypes = new ArrayList<String>(Arrays.asList(fileTypes)); |
| 65 mCapture = capture; | 70 mCapture = capture; |
| 66 | 71 |
| 67 Intent chooser = new Intent(Intent.ACTION_CHOOSER); | 72 Intent chooser = new Intent(Intent.ACTION_CHOOSER); |
| 68 Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); | 73 Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); |
| 69 mCameraOutputUri = Uri.fromFile(getFileForImageCapture()); | 74 camera.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | |
| 75 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
| 76 Context context = window.getApplicationContext(); |
| 77 try { |
| 78 mCameraOutputUri = ContentUriUtils.getContentUriFromFile( |
| 79 context, getFileForImageCapture(context)); |
| 80 } catch (IOException e) { |
| 81 Log.e(TAG, "Cannot retrieve content uri from file", e); |
| 82 } |
| 83 if (mCameraOutputUri == null) { |
| 84 onFileNotSelected(); |
| 85 return; |
| 86 } |
| 87 |
| 70 camera.putExtra(MediaStore.EXTRA_OUTPUT, mCameraOutputUri); | 88 camera.putExtra(MediaStore.EXTRA_OUTPUT, mCameraOutputUri); |
| 89 camera.setClipData( |
| 90 ClipData.newUri(context.getContentResolver(), IMAGE_FILE_PATH, m
CameraOutputUri)); |
| 71 Intent camcorder = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); | 91 Intent camcorder = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); |
| 72 Intent soundRecorder = new Intent( | 92 Intent soundRecorder = new Intent( |
| 73 MediaStore.Audio.Media.RECORD_SOUND_ACTION); | 93 MediaStore.Audio.Media.RECORD_SOUND_ACTION); |
| 74 | 94 |
| 75 // Quick check - if the |capture| parameter is set and |fileTypes| has t
he appropriate MIME | 95 // Quick check - if the |capture| parameter is set and |fileTypes| has t
he appropriate MIME |
| 76 // type, we should just launch the appropriate intent. Otherwise build u
p a chooser based on | 96 // type, we should just launch the appropriate intent. Otherwise build u
p a chooser based on |
| 77 // the accept type and then display that to the user. | 97 // the accept type and then display that to the user. |
| 78 if (captureCamera()) { | 98 if (captureCamera()) { |
| 79 if (window.showIntent(camera, this, R.string.low_memory_error)) retu
rn; | 99 if (window.showIntent(camera, this, R.string.low_memory_error)) retu
rn; |
| 80 } else if (captureCamcorder()) { | 100 } else if (captureCamcorder()) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 extraIntents.toArray(new Intent[] { })); | 138 extraIntents.toArray(new Intent[] { })); |
| 119 | 139 |
| 120 chooser.putExtra(Intent.EXTRA_INTENT, getContentIntent); | 140 chooser.putExtra(Intent.EXTRA_INTENT, getContentIntent); |
| 121 | 141 |
| 122 if (!window.showIntent(chooser, this, R.string.low_memory_error)) { | 142 if (!window.showIntent(chooser, this, R.string.low_memory_error)) { |
| 123 onFileNotSelected(); | 143 onFileNotSelected(); |
| 124 } | 144 } |
| 125 } | 145 } |
| 126 | 146 |
| 127 /** | 147 /** |
| 128 * Get a file for the image capture in the CAPTURE_IMAGE_DIRECTORY directory
. | 148 * Get a file for the image capture in the IMAGE_FILE_PATH directory. |
| 149 * @param context The application context. |
| 129 */ | 150 */ |
| 130 private File getFileForImageCapture() { | 151 private File getFileForImageCapture(Context context) throws IOException { |
| 131 File externalDataDir = Environment.getExternalStoragePublicDirectory( | 152 final File path = new File(context.getFilesDir(), IMAGE_FILE_PATH); |
| 132 Environment.DIRECTORY_DCIM); | 153 if (!path.exists() && !path.mkdir()) { |
| 133 File cameraDataDir = new File(externalDataDir.getAbsolutePath() + | 154 throw new IOException("Folder cannot be created."); |
| 134 File.separator + CAPTURE_IMAGE_DIRECTORY); | |
| 135 if (!cameraDataDir.exists() && !cameraDataDir.mkdirs()) { | |
| 136 cameraDataDir = externalDataDir; | |
| 137 } | 155 } |
| 138 File photoFile = new File(cameraDataDir.getAbsolutePath() + | 156 File photoFile = File.createTempFile( |
| 139 File.separator + System.currentTimeMillis() + ".jpg"); | 157 String.valueOf(System.currentTimeMillis()), ".jpg", path); |
| 140 return photoFile; | 158 return photoFile; |
| 141 } | 159 } |
| 142 | 160 |
| 143 /** | 161 /** |
| 144 * Callback method to handle the intent results and pass on the path to the
native | 162 * Callback method to handle the intent results and pass on the path to the
native |
| 145 * SelectFileDialog. | 163 * SelectFileDialog. |
| 146 * @param window The window that has access to the application activity. | 164 * @param window The window that has access to the application activity. |
| 147 * @param resultCode The result code whether the intent returned successfull
y. | 165 * @param resultCode The result code whether the intent returned successfull
y. |
| 148 * @param contentResolver The content resolver used to extract the path of t
he selected file. | 166 * @param contentResolver The content resolver used to extract the path of t
he selected file. |
| 149 * @param results The results of the requested intent. | 167 * @param results The results of the requested intent. |
| 150 */ | 168 */ |
| 151 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) | 169 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) |
| 152 @Override | 170 @Override |
| 153 public void onIntentCompleted(WindowAndroid window, int resultCode, | 171 public void onIntentCompleted(WindowAndroid window, int resultCode, |
| 154 ContentResolver contentResolver, Intent results) { | 172 ContentResolver contentResolver, Intent results) { |
| 155 if (resultCode != Activity.RESULT_OK) { | 173 if (resultCode != Activity.RESULT_OK) { |
| 156 onFileNotSelected(); | 174 onFileNotSelected(); |
| 157 return; | 175 return; |
| 158 } | 176 } |
| 159 | 177 |
| 160 if (results == null) { | 178 if (results == null) { |
| 161 // If we have a successful return but no data, then assume this is t
he camera returning | 179 // If we have a successful return but no data, then assume this is t
he camera returning |
| 162 // the photo that we requested. | 180 // the photo that we requested. |
| 163 nativeOnFileSelected(mNativeSelectFileDialog, mCameraOutputUri.getPa
th(), ""); | 181 nativeOnFileSelected(mNativeSelectFileDialog, mCameraOutputUri.toStr
ing(), |
| 182 mCameraOutputUri.getLastPathSegment()); |
| 164 | 183 |
| 165 // Broadcast to the media scanner that there's a new photo on the de
vice so it will | 184 // Broadcast to the media scanner that there's a new photo on the de
vice so it will |
| 166 // show up right away in the gallery (rather than waiting until the
next time the media | 185 // show up right away in the gallery (rather than waiting until the
next time the media |
| 167 // scanner runs). | 186 // scanner runs). |
| 168 window.sendBroadcast(new Intent( | 187 window.sendBroadcast(new Intent( |
| 169 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mCameraOutputUri)); | 188 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mCameraOutputUri)); |
| 170 return; | 189 return; |
| 171 } | 190 } |
| 172 | 191 |
| 173 // Path for when EXTRA_ALLOW_MULTIPLE Intent extra has been defined. Eac
h of the selected | 192 // Path for when EXTRA_ALLOW_MULTIPLE Intent extra has been defined. Eac
h of the selected |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 private static SelectFileDialog create(long nativeSelectFileDialog) { | 318 private static SelectFileDialog create(long nativeSelectFileDialog) { |
| 300 return new SelectFileDialog(nativeSelectFileDialog); | 319 return new SelectFileDialog(nativeSelectFileDialog); |
| 301 } | 320 } |
| 302 | 321 |
| 303 private native void nativeOnFileSelected(long nativeSelectFileDialogImpl, | 322 private native void nativeOnFileSelected(long nativeSelectFileDialogImpl, |
| 304 String filePath, String displayName); | 323 String filePath, String displayName); |
| 305 private native void nativeOnMultipleFilesSelected(long nativeSelectFileDialo
gImpl, | 324 private native void nativeOnMultipleFilesSelected(long nativeSelectFileDialo
gImpl, |
| 306 String[] filePathArray, String[] displayNameArray); | 325 String[] filePathArray, String[] displayNameArray); |
| 307 private native void nativeOnFileNotSelected(long nativeSelectFileDialogImpl)
; | 326 private native void nativeOnFileNotSelected(long nativeSelectFileDialogImpl)
; |
| 308 } | 327 } |
| OLD | NEW |