blob: 2041ecf19e0780f5577906fef3ef2fb84626366c [file] [log] [blame]
Michael Kolb8233fac2010-10-26 16:08:53 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
Michael Kolb8233fac2010-10-26 16:08:53 -070018
19import android.app.Activity;
Ben Murdoche4c0cae2011-02-18 11:25:38 +000020import android.content.ActivityNotFoundException;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070021import android.content.ComponentName;
Vivek Sekharb54614f2014-05-01 19:03:37 -070022import android.content.ContentResolver;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070023import android.content.ContentUris;
24import android.content.Context;
Michael Kolb8233fac2010-10-26 16:08:53 -070025import android.content.Intent;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070026import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
28import android.content.pm.ActivityInfo;
kaiyiz4b59d262013-07-30 10:41:38 +080029import android.database.Cursor;
Michael Kolb8233fac2010-10-26 16:08:53 -070030import android.net.Uri;
31import android.os.Environment;
32import android.provider.MediaStore;
33import android.webkit.ValueCallback;
Vivek Sekharb54614f2014-05-01 19:03:37 -070034import android.util.Log;
Ben Murdoche4c0cae2011-02-18 11:25:38 +000035import android.widget.Toast;
Michael Kolb8233fac2010-10-26 16:08:53 -070036
Bijan Amirzada41242f22014-03-21 12:12:18 -070037import com.android.browser.R;
38import com.android.browser.reflect.ReflectHelper;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080039
Michael Kolb8233fac2010-10-26 16:08:53 -070040import java.io.File;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070041import java.util.ArrayList;
42import java.util.List;
Michael Kolb8233fac2010-10-26 16:08:53 -070043
44/**
45 * Handle the file upload callbacks from WebView here
46 */
47public class UploadHandler {
48
Vivek Sekharb54614f2014-05-01 19:03:37 -070049 private static final String TAG = "UploadHandler";
Michael Kolb8233fac2010-10-26 16:08:53 -070050 /*
51 * The Object used to inform the WebView of the file to upload.
52 */
53 private ValueCallback<Uri> mUploadMessage;
Vivek Sekharb54614f2014-05-01 19:03:37 -070054 private ValueCallback<String[]> mUploadFilePaths;
Michael Kolb8233fac2010-10-26 16:08:53 -070055 private String mCameraFilePath;
56
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000057 private boolean mHandled;
58 private boolean mCaughtActivityNotFoundException;
59
Michael Kolb8233fac2010-10-26 16:08:53 -070060 private Controller mController;
61
62 public UploadHandler(Controller controller) {
63 mController = controller;
64 }
65
66 String getFilePath() {
67 return mCameraFilePath;
68 }
69
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070070 protected boolean handled() {
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000071 return mHandled;
72 }
73
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070074 protected void setHandled(boolean handled) {
75 mHandled = handled;
76 mCaughtActivityNotFoundException = false;
77 if (!mHandled)
78 mUploadFilePaths.onReceiveValue(null);
79 }
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000080
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070081 void onResult(int resultCode, Intent intent) {
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000082 if (resultCode == Activity.RESULT_CANCELED && mCaughtActivityNotFoundException) {
83 // Couldn't resolve an activity, we are going to try again so skip
84 // this result.
85 mCaughtActivityNotFoundException = false;
86 return;
87 }
88
Michael Kolb8233fac2010-10-26 16:08:53 -070089 Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
90 : intent.getData();
91
92 // As we ask the camera to save the result of the user taking
93 // a picture, the camera application does not return anything other
94 // than RESULT_OK. So we need to check whether the file we expected
95 // was written to disk in the in the case that we
96 // did not get an intent returned but did get a RESULT_OK. If it was,
97 // we assume that this result has came back from the camera.
98 if (result == null && intent == null && resultCode == Activity.RESULT_OK) {
99 File cameraFile = new File(mCameraFilePath);
100 if (cameraFile.exists()) {
101 result = Uri.fromFile(cameraFile);
102 // Broadcast to the media scanner that we have a new photo
103 // so it will be added into the gallery for the user.
104 mController.getActivity().sendBroadcast(
105 new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
106 }
107 }
108
Vivek Sekharb54614f2014-05-01 19:03:37 -0700109 boolean hasGoodFilePath = false;
110 String filePath = null;
111 if (result != null) {
112 String scheme = result.getScheme();
Axesh R. Ajmerac3d90452014-10-29 18:12:19 -0700113 // try to get local file path from uri
Vivek Sekharb54614f2014-05-01 19:03:37 -0700114 if ("file".equals(scheme)) {
115 filePath = result.getPath();
116 hasGoodFilePath = filePath != null && !filePath.isEmpty();
117 } else if ("content".equals(scheme)) {
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700118 filePath = getFilePath(mController.getContext(), result);
119 hasGoodFilePath = filePath != null && !filePath.isEmpty();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700120 }
Axesh R. Ajmerac3d90452014-10-29 18:12:19 -0700121
122 // The native layer only accepts path based on file scheme
123 // and skips anything else passed to it
124 filePath = "file://"+filePath;
Vivek Sekharb54614f2014-05-01 19:03:37 -0700125 }
126
Panos Thomas4bdb5252014-11-13 16:20:11 -0800127 // Add for carrier feature - prevent uploading DRM type files based on file extension. This
128 // is not a secure implementation since malicious users can trivially modify the filename.
129 // DRM files can be securely detected by inspecting their integrity protected content.
130 boolean drmUploadEnabled = BrowserConfig.getInstance(mController.getContext())
131 .hasFeature(BrowserConfig.Feature.DRM_UPLOADS);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700132 boolean isDRMFileType = false;
Bijan Amirzadae75909d2014-05-06 14:18:54 -0700133 if (drmUploadEnabled && filePath != null
Vivek Sekharb54614f2014-05-01 19:03:37 -0700134 && (filePath.endsWith(".fl") || filePath.endsWith(".dm")
135 || filePath.endsWith(".dcf") || filePath.endsWith(".dr")
136 || filePath.endsWith(".dd"))) {
137 isDRMFileType = true;
138 Toast.makeText(mController.getContext(), R.string.drm_file_unsupported,
139 Toast.LENGTH_LONG).show();
140 }
141
142 if (mUploadMessage != null) {
143 if (!isDRMFileType) {
144 mUploadMessage.onReceiveValue(result);
145 } else {
146 mUploadMessage.onReceiveValue(null);
147 }
148 }
149
150 if (mUploadFilePaths != null) {
151 if (hasGoodFilePath && !isDRMFileType) {
152 Log.d(TAG, "upload file path:" + filePath);
Axesh R. Ajmerac3d90452014-10-29 18:12:19 -0700153
Vivek Sekharb54614f2014-05-01 19:03:37 -0700154 mUploadFilePaths.onReceiveValue(new String[]{filePath});
155 } else {
156 mUploadFilePaths.onReceiveValue(null);
157 }
kaiyiz4b59d262013-07-30 10:41:38 +0800158 }
159
Ben Murdoch51f6a2f2011-02-21 12:27:07 +0000160 mHandled = true;
161 mCaughtActivityNotFoundException = false;
Michael Kolb8233fac2010-10-26 16:08:53 -0700162 }
163
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700164
165 public String getDocumentId(final Uri uri) {
166 String id = null;
167 try {
168 Object[] params = {(android.net.Uri)uri};
169 Class[] type = new Class[] {Class.forName("android.net.Uri") };
170 id = (String) ReflectHelper.invokeMethod(
171 "android.provider.DocumentsContract","getDocumentId",
172 type, params);
173
174 } catch(java.lang.ClassNotFoundException e) {
175
176 }
177 return id;
178 }
179
180
181 public String getFilePath(final Context context, final Uri uri) {
182 String id = getDocumentId(uri);
183
184 // DocumentProvider is new API exposed in Kitkat
185 // Its a way of exposing unified file explorer
186 if (id != null) {
187 // ExternalStorageProvider
188 if (isExternalStorageDocument(uri)) {
189 final String docId = id;
190 final String[] split = docId.split(":");
191 final String type = split[0];
192
193 if ("primary".equalsIgnoreCase(type)) {
194 return Environment.getExternalStorageDirectory() + "/" + split[1];
195 }
196 }
197 // DownloadsProvider
198 else if (isDownloadsDocument(uri)) {
199 final Uri contentUri = ContentUris.withAppendedId(
200 Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
201 return getDataColumn(context, contentUri, null, null);
202 }
203 // MediaProvider
204 else if (isMediaDocument(uri)) {
205 final String docId = id;
206 final String[] split = docId.split(":");
207 final String type = split[0];
208
209 Uri contentUri = null;
210 if ("image".equals(type)) {
211 contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
212 } else if ("video".equals(type)) {
213 contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
214 } else if ("audio".equals(type)) {
215 contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
216 }
217
218 final String selection = "_id=?";
219 final String[] selectionArgs = new String[] {
220 split[1]
221 };
222
223 return getDataColumn(context, contentUri, selection, selectionArgs);
224 }
225 }
226 // MediaStore (and general)
227 else if ("content".equalsIgnoreCase(uri.getScheme())) {
228 return getDataColumn(context, uri, null, null);
229 }
230
231 return null;
232 }
233
234 /**
235 * Get the value of the data column for this Uri. This is useful for
236 * MediaStore Uris, and other file-based ContentProviders.
237 * @return The value of the _data column, which is typically a file path.
238 */
239 private String getDataColumn(Context context, Uri uri, String selection,
240 String[] selectionArgs) {
241
242 Cursor cursor = null;
243 final String column = "_data";
244 final String[] projection = { column };
245
246 try {
247 cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
248 null);
249 if (cursor != null && cursor.moveToFirst()) {
250 final int column_index = cursor.getColumnIndexOrThrow(column);
251 return cursor.getString(column_index);
252 }
253 } finally {
254 if (cursor != null)
255 cursor.close();
256 }
257 return null;
258 }
259
260 /**
261 * @return Whether the Uri authority is ExternalStorageProvider.
262 */
263 private boolean isExternalStorageDocument(Uri uri) {
264 return "com.android.externalstorage.documents".equals(uri.getAuthority());
265 }
266
267 /**
268 * @return Whether the Uri authority is DownloadsProvider.
269 */
270 private boolean isDownloadsDocument(Uri uri) {
271 return "com.android.providers.downloads.documents".equals(uri.getAuthority());
272 }
273
274 /**
275 * @return Whether the Uri authority is MediaProvider.
276 */
277 public static boolean isMediaDocument(Uri uri) {
278 return "com.android.providers.media.documents".equals(uri.getAuthority());
279 }
280
281
Ben Murdoch8cad4132012-01-11 10:56:43 +0000282 void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700283
284 final String imageMimeType = "image/*";
285 final String videoMimeType = "video/*";
286 final String audioMimeType = "audio/*";
287 final String mediaSourceKey = "capture";
288 final String mediaSourceValueCamera = "camera";
289 final String mediaSourceValueFileSystem = "filesystem";
290 final String mediaSourceValueCamcorder = "camcorder";
291 final String mediaSourceValueMicrophone = "microphone";
292
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000293 // According to the spec, media source can be 'filesystem' or 'camera' or 'camcorder'
Ben Murdoch8cad4132012-01-11 10:56:43 +0000294 // or 'microphone' and the default value should be 'filesystem'.
295 String mediaSource = mediaSourceValueFileSystem;
Michael Kolb8233fac2010-10-26 16:08:53 -0700296
Michael Kolb8233fac2010-10-26 16:08:53 -0700297 if (mUploadMessage != null) {
298 // Already a file picker operation in progress.
299 return;
300 }
301
302 mUploadMessage = uploadMsg;
303
304 // Parse the accept type.
305 String params[] = acceptType.split(";");
306 String mimeType = params[0];
307
Ben Murdoch8cad4132012-01-11 10:56:43 +0000308 if (capture.length() > 0) {
309 mediaSource = capture;
310 }
311
312 if (capture.equals(mediaSourceValueFileSystem)) {
313 // To maintain backwards compatibility with the previous implementation
314 // of the media capture API, if the value of the 'capture' attribute is
315 // "filesystem", we should examine the accept-type for a MIME type that
316 // may specify a different capture value.
317 for (String p : params) {
318 String[] keyValue = p.split("=");
319 if (keyValue.length == 2) {
320 // Process key=value parameters.
321 if (mediaSourceKey.equals(keyValue[0])) {
322 mediaSource = keyValue[1];
323 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700324 }
325 }
326 }
327
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000328 //Ensure it is not still set from a previous upload.
329 mCameraFilePath = null;
330
331 if (mimeType.equals(imageMimeType)) {
332 if (mediaSource.equals(mediaSourceValueCamera)) {
333 // Specified 'image/*' and requested the camera, so go ahead and launch the
334 // camera directly.
335 startActivity(createCameraIntent());
336 return;
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000337 } else {
Ben Murdoch8cad4132012-01-11 10:56:43 +0000338 // Specified just 'image/*', capture=filesystem, or an invalid capture parameter.
339 // In all these cases we show a traditional picker filetered on accept type
340 // so launch an intent for both the Camera and image/* OPENABLE.
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000341 Intent chooser = createChooserIntent(createCameraIntent());
342 chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
343 startActivity(chooser);
344 return;
345 }
346 } else if (mimeType.equals(videoMimeType)) {
347 if (mediaSource.equals(mediaSourceValueCamcorder)) {
348 // Specified 'video/*' and requested the camcorder, so go ahead and launch the
349 // camcorder directly.
350 startActivity(createCamcorderIntent());
351 return;
Ben Murdoch8cad4132012-01-11 10:56:43 +0000352 } else {
353 // Specified just 'video/*', capture=filesystem or an invalid capture parameter.
354 // In all these cases we show an intent for the traditional file picker, filtered
355 // on accept type so launch an intent for both camcorder and video/* OPENABLE.
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000356 Intent chooser = createChooserIntent(createCamcorderIntent());
357 chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
358 startActivity(chooser);
359 return;
360 }
361 } else if (mimeType.equals(audioMimeType)) {
362 if (mediaSource.equals(mediaSourceValueMicrophone)) {
363 // Specified 'audio/*' and requested microphone, so go ahead and launch the sound
364 // recorder.
365 startActivity(createSoundRecorderIntent());
366 return;
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000367 } else {
Ben Murdoch8cad4132012-01-11 10:56:43 +0000368 // Specified just 'audio/*', capture=filesystem of an invalid capture parameter.
369 // In all these cases so go ahead and launch an intent for both the sound
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000370 // recorder and audio/* OPENABLE.
371 Intent chooser = createChooserIntent(createSoundRecorderIntent());
372 chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
373 startActivity(chooser);
374 return;
375 }
376 }
377
378 // No special handling based on the accept type was necessary, so trigger the default
379 // file upload chooser.
380 startActivity(createDefaultOpenableIntent());
381 }
382
Vivek Sekharb54614f2014-05-01 19:03:37 -0700383 void showFileChooser(ValueCallback<String[]> uploadFilePaths, String acceptTypes,
384 boolean capture) {
385
386 final String imageMimeType = "image/*";
387 final String videoMimeType = "video/*";
388 final String audioMimeType = "audio/*";
389
390 if (mUploadFilePaths != null) {
391 // Already a file picker operation in progress.
392 return;
393 }
394
395 mUploadFilePaths = uploadFilePaths;
396
397 // Parse the accept type.
398 String params[] = acceptTypes.split(";");
399 String mimeType = params[0];
400
401 // Ensure it is not still set from a previous upload.
402 mCameraFilePath = null;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700403 List<Intent> intentList = new ArrayList<Intent>();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700404
405 if (mimeType.equals(imageMimeType)) {
406 if (capture) {
407 // Specified 'image/*' and capture=true, so go ahead and launch the
408 // camera directly.
409 startActivity(createCameraIntent());
410 return;
411 } else {
412 // Specified just 'image/*', capture=false, or no capture value.
413 // In all these cases we show a traditional picker filetered on accept type
414 // so launch an intent for both the Camera and image/* OPENABLE.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700415 intentList.add(createCameraIntent());
416 createUploadDialog(imageMimeType, intentList);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700417 return;
418 }
419 } else if (mimeType.equals(videoMimeType)) {
420 if (capture) {
421 // Specified 'video/*' and capture=true, so go ahead and launch the
422 // camcorder directly.
423 startActivity(createCamcorderIntent());
424 return;
425 } else {
426 // Specified just 'video/*', capture=false, or no capture value.
427 // In all these cases we show an intent for the traditional file picker, filtered
428 // on accept type so launch an intent for both camcorder and video/* OPENABLE.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700429 intentList.add(createCamcorderIntent());
430 createUploadDialog(videoMimeType, intentList);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700431 return;
432 }
433 } else if (mimeType.equals(audioMimeType)) {
434 if (capture) {
435 // Specified 'audio/*' and capture=true, so go ahead and launch the sound
436 // recorder.
437 startActivity(createSoundRecorderIntent());
438 return;
439 } else {
440 // Specified just 'audio/*', capture=false, or no capture value.
441 // In all these cases so go ahead and launch an intent for both the sound
442 // recorder and audio/* OPENABLE.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700443 intentList.add(createSoundRecorderIntent());
444 createUploadDialog(audioMimeType, intentList);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700445 return;
446 }
447 }
448
449 // No special handling based on the accept type was necessary, so trigger the default
450 // file upload chooser.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700451 createUploadDialog("*/*", null);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700452 }
453
454
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000455 private void startActivity(Intent intent) {
456 try {
457 mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
458 } catch (ActivityNotFoundException e) {
459 // No installed app was able to handle the intent that
460 // we sent, so fallback to the default file upload control.
461 try {
Ben Murdoch51f6a2f2011-02-21 12:27:07 +0000462 mCaughtActivityNotFoundException = true;
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000463 mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
464 Controller.FILE_SELECTED);
465 } catch (ActivityNotFoundException e2) {
466 // Nothing can return us a file, so file upload is effectively disabled.
467 Toast.makeText(mController.getActivity(), R.string.uploads_disabled,
468 Toast.LENGTH_LONG).show();
469 }
470 }
471 }
472
473 private Intent createDefaultOpenableIntent() {
474 // Create and return a chooser with the default OPENABLE
475 // actions including the camera, camcorder and sound
476 // recorder where available.
Michael Kolb8233fac2010-10-26 16:08:53 -0700477 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
478 i.addCategory(Intent.CATEGORY_OPENABLE);
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000479 i.setType("*/*");
Michael Kolb8233fac2010-10-26 16:08:53 -0700480
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000481 Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
482 createSoundRecorderIntent());
483 chooser.putExtra(Intent.EXTRA_INTENT, i);
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700484
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000485 return chooser;
486 }
487
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700488
489 private void createUploadDialog(String openableMimeType, List<Intent> intentList) {
490
491 Intent openable = new Intent(Intent.ACTION_GET_CONTENT);
492 openable.addCategory(Intent.CATEGORY_OPENABLE);
493 openable.setType(openableMimeType);
494
495 if (openableMimeType.equals("*/*") && intentList == null) {
496 intentList = new ArrayList<Intent>();
497 intentList.add(createCameraIntent());
498 intentList.add(createCamcorderIntent());
499 intentList.add(createSoundRecorderIntent());
500 }
501
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700502 PackageManager pm = mController.getActivity().getPackageManager();
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700503 ArrayList<ResolveInfo> uploadApps = new ArrayList<ResolveInfo>();
504
505 //Step 1:- resolve all apps for IntentList passed
506 for (Intent i: intentList) {
507 List<ResolveInfo> intentAppsList = pm.queryIntentActivities(i,
508 PackageManager.MATCH_DEFAULT_ONLY);
509 // limit only to first activity
510 uploadApps.add(intentAppsList.get(0));
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700511 }
512
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700513 // Step 2:- get all openable apps list and create corresponding intents
514 List<ResolveInfo> openableAppsList = pm.queryIntentActivities(openable,
515 PackageManager.MATCH_DEFAULT_ONLY);
516 // limit only to first activity
517 ResolveInfo topOpenableApp = openableAppsList.get(0);
518 uploadApps.add(topOpenableApp);
519 ActivityInfo activityInfo = topOpenableApp.activityInfo;
520 ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,
521 activityInfo.name);
522 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
523 i.setType(openableMimeType);
524 i.setComponent(name);
525 intentList.add(i);
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700526
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700527 // Step 3: Pass all the apps and their corresponding intents to uploaddialog
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700528 UploadDialog upDialog = new UploadDialog(mController.getActivity());
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700529 upDialog.getUploadableApps(uploadApps, intentList);
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700530 upDialog.loadView(this);
531 }
532
533 public void initiateActivity(Intent intent) {
534 startActivity(intent);
535 }
536
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000537 private Intent createChooserIntent(Intent... intents) {
538 Intent chooser = new Intent(Intent.ACTION_CHOOSER);
539 chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
540 chooser.putExtra(Intent.EXTRA_TITLE,
541 mController.getActivity().getResources()
542 .getString(R.string.choose_upload));
543 return chooser;
544 }
545
546 private Intent createOpenableIntent(String type) {
547 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
548 i.addCategory(Intent.CATEGORY_OPENABLE);
549 i.setType(type);
550 return i;
551 }
552
553 private Intent createCameraIntent() {
Michael Kolb8233fac2010-10-26 16:08:53 -0700554 Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
555 File externalDataDir = Environment.getExternalStoragePublicDirectory(
556 Environment.DIRECTORY_DCIM);
557 File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
558 File.separator + "browser-photos");
559 cameraDataDir.mkdirs();
560 mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
561 System.currentTimeMillis() + ".jpg";
562 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000563 return cameraIntent;
Michael Kolb8233fac2010-10-26 16:08:53 -0700564 }
565
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000566 private Intent createCamcorderIntent() {
567 return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
568 }
569
570 private Intent createSoundRecorderIntent() {
571 return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
Michael Kolb8233fac2010-10-26 16:08:53 -0700572 }
573
574}