blob: 6b0a39f94ef313a033641b8f8b4db2bab2ea761b [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;
Axesh R. Ajmeracdbedf12014-12-09 15:25:40 -080042import java.util.Iterator;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070043import java.util.List;
Michael Kolb8233fac2010-10-26 16:08:53 -070044
45/**
46 * Handle the file upload callbacks from WebView here
47 */
48public class UploadHandler {
49
Vivek Sekharb54614f2014-05-01 19:03:37 -070050 private static final String TAG = "UploadHandler";
Michael Kolb8233fac2010-10-26 16:08:53 -070051 /*
52 * The Object used to inform the WebView of the file to upload.
53 */
54 private ValueCallback<Uri> mUploadMessage;
Vivek Sekharb54614f2014-05-01 19:03:37 -070055 private ValueCallback<String[]> mUploadFilePaths;
Michael Kolb8233fac2010-10-26 16:08:53 -070056 private String mCameraFilePath;
57
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000058 private boolean mHandled;
59 private boolean mCaughtActivityNotFoundException;
60
Michael Kolb8233fac2010-10-26 16:08:53 -070061 private Controller mController;
62
63 public UploadHandler(Controller controller) {
64 mController = controller;
65 }
66
67 String getFilePath() {
68 return mCameraFilePath;
69 }
70
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070071 protected boolean handled() {
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000072 return mHandled;
73 }
74
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070075 protected void setHandled(boolean handled) {
76 mHandled = handled;
77 mCaughtActivityNotFoundException = false;
78 if (!mHandled)
79 mUploadFilePaths.onReceiveValue(null);
80 }
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000081
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -070082 void onResult(int resultCode, Intent intent) {
Ben Murdoch51f6a2f2011-02-21 12:27:07 +000083 if (resultCode == Activity.RESULT_CANCELED && mCaughtActivityNotFoundException) {
84 // Couldn't resolve an activity, we are going to try again so skip
85 // this result.
86 mCaughtActivityNotFoundException = false;
87 return;
88 }
89
Michael Kolb8233fac2010-10-26 16:08:53 -070090 Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
91 : intent.getData();
92
93 // As we ask the camera to save the result of the user taking
94 // a picture, the camera application does not return anything other
95 // than RESULT_OK. So we need to check whether the file we expected
96 // was written to disk in the in the case that we
97 // did not get an intent returned but did get a RESULT_OK. If it was,
98 // we assume that this result has came back from the camera.
99 if (result == null && intent == null && resultCode == Activity.RESULT_OK) {
100 File cameraFile = new File(mCameraFilePath);
101 if (cameraFile.exists()) {
102 result = Uri.fromFile(cameraFile);
103 // Broadcast to the media scanner that we have a new photo
104 // so it will be added into the gallery for the user.
105 mController.getActivity().sendBroadcast(
106 new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
107 }
108 }
109
Vivek Sekharb54614f2014-05-01 19:03:37 -0700110 boolean hasGoodFilePath = false;
111 String filePath = null;
112 if (result != null) {
113 String scheme = result.getScheme();
Axesh R. Ajmerac3d90452014-10-29 18:12:19 -0700114 // try to get local file path from uri
Vivek Sekharb54614f2014-05-01 19:03:37 -0700115 if ("file".equals(scheme)) {
116 filePath = result.getPath();
117 hasGoodFilePath = filePath != null && !filePath.isEmpty();
118 } else if ("content".equals(scheme)) {
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700119 filePath = getFilePath(mController.getContext(), result);
120 hasGoodFilePath = filePath != null && !filePath.isEmpty();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700121 }
Axesh R. Ajmerac3d90452014-10-29 18:12:19 -0700122
123 // The native layer only accepts path based on file scheme
124 // and skips anything else passed to it
125 filePath = "file://"+filePath;
Vivek Sekharb54614f2014-05-01 19:03:37 -0700126 }
127
Panos Thomas4bdb5252014-11-13 16:20:11 -0800128 // Add for carrier feature - prevent uploading DRM type files based on file extension. This
129 // is not a secure implementation since malicious users can trivially modify the filename.
130 // DRM files can be securely detected by inspecting their integrity protected content.
131 boolean drmUploadEnabled = BrowserConfig.getInstance(mController.getContext())
132 .hasFeature(BrowserConfig.Feature.DRM_UPLOADS);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700133 boolean isDRMFileType = false;
Bijan Amirzadae75909d2014-05-06 14:18:54 -0700134 if (drmUploadEnabled && filePath != null
Vivek Sekharb54614f2014-05-01 19:03:37 -0700135 && (filePath.endsWith(".fl") || filePath.endsWith(".dm")
136 || filePath.endsWith(".dcf") || filePath.endsWith(".dr")
137 || filePath.endsWith(".dd"))) {
138 isDRMFileType = true;
139 Toast.makeText(mController.getContext(), R.string.drm_file_unsupported,
140 Toast.LENGTH_LONG).show();
141 }
142
143 if (mUploadMessage != null) {
144 if (!isDRMFileType) {
145 mUploadMessage.onReceiveValue(result);
146 } else {
147 mUploadMessage.onReceiveValue(null);
148 }
149 }
150
151 if (mUploadFilePaths != null) {
152 if (hasGoodFilePath && !isDRMFileType) {
153 Log.d(TAG, "upload file path:" + filePath);
Axesh R. Ajmerac3d90452014-10-29 18:12:19 -0700154
Vivek Sekharb54614f2014-05-01 19:03:37 -0700155 mUploadFilePaths.onReceiveValue(new String[]{filePath});
156 } else {
157 mUploadFilePaths.onReceiveValue(null);
158 }
kaiyiz4b59d262013-07-30 10:41:38 +0800159 }
160
Ben Murdoch51f6a2f2011-02-21 12:27:07 +0000161 mHandled = true;
162 mCaughtActivityNotFoundException = false;
Michael Kolb8233fac2010-10-26 16:08:53 -0700163 }
164
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700165
166 public String getDocumentId(final Uri uri) {
167 String id = null;
168 try {
169 Object[] params = {(android.net.Uri)uri};
170 Class[] type = new Class[] {Class.forName("android.net.Uri") };
171 id = (String) ReflectHelper.invokeMethod(
172 "android.provider.DocumentsContract","getDocumentId",
173 type, params);
174
175 } catch(java.lang.ClassNotFoundException e) {
176
177 }
178 return id;
179 }
180
181
182 public String getFilePath(final Context context, final Uri uri) {
183 String id = getDocumentId(uri);
184
185 // DocumentProvider is new API exposed in Kitkat
186 // Its a way of exposing unified file explorer
187 if (id != null) {
188 // ExternalStorageProvider
189 if (isExternalStorageDocument(uri)) {
190 final String docId = id;
191 final String[] split = docId.split(":");
192 final String type = split[0];
193
194 if ("primary".equalsIgnoreCase(type)) {
195 return Environment.getExternalStorageDirectory() + "/" + split[1];
196 }
197 }
198 // DownloadsProvider
199 else if (isDownloadsDocument(uri)) {
200 final Uri contentUri = ContentUris.withAppendedId(
201 Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
202 return getDataColumn(context, contentUri, null, null);
203 }
204 // MediaProvider
205 else if (isMediaDocument(uri)) {
206 final String docId = id;
207 final String[] split = docId.split(":");
208 final String type = split[0];
209
210 Uri contentUri = null;
211 if ("image".equals(type)) {
212 contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
213 } else if ("video".equals(type)) {
214 contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
215 } else if ("audio".equals(type)) {
216 contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
217 }
218
219 final String selection = "_id=?";
220 final String[] selectionArgs = new String[] {
221 split[1]
222 };
223
224 return getDataColumn(context, contentUri, selection, selectionArgs);
225 }
226 }
227 // MediaStore (and general)
228 else if ("content".equalsIgnoreCase(uri.getScheme())) {
229 return getDataColumn(context, uri, null, null);
230 }
231
232 return null;
233 }
234
235 /**
236 * Get the value of the data column for this Uri. This is useful for
237 * MediaStore Uris, and other file-based ContentProviders.
238 * @return The value of the _data column, which is typically a file path.
239 */
240 private String getDataColumn(Context context, Uri uri, String selection,
241 String[] selectionArgs) {
242
243 Cursor cursor = null;
244 final String column = "_data";
245 final String[] projection = { column };
246
247 try {
248 cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
249 null);
250 if (cursor != null && cursor.moveToFirst()) {
251 final int column_index = cursor.getColumnIndexOrThrow(column);
252 return cursor.getString(column_index);
253 }
254 } finally {
255 if (cursor != null)
256 cursor.close();
257 }
258 return null;
259 }
260
261 /**
262 * @return Whether the Uri authority is ExternalStorageProvider.
263 */
264 private boolean isExternalStorageDocument(Uri uri) {
265 return "com.android.externalstorage.documents".equals(uri.getAuthority());
266 }
267
268 /**
269 * @return Whether the Uri authority is DownloadsProvider.
270 */
271 private boolean isDownloadsDocument(Uri uri) {
272 return "com.android.providers.downloads.documents".equals(uri.getAuthority());
273 }
274
275 /**
276 * @return Whether the Uri authority is MediaProvider.
277 */
278 public static boolean isMediaDocument(Uri uri) {
279 return "com.android.providers.media.documents".equals(uri.getAuthority());
280 }
281
282
Ben Murdoch8cad4132012-01-11 10:56:43 +0000283 void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700284
285 final String imageMimeType = "image/*";
286 final String videoMimeType = "video/*";
287 final String audioMimeType = "audio/*";
288 final String mediaSourceKey = "capture";
289 final String mediaSourceValueCamera = "camera";
290 final String mediaSourceValueFileSystem = "filesystem";
291 final String mediaSourceValueCamcorder = "camcorder";
292 final String mediaSourceValueMicrophone = "microphone";
293
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000294 // According to the spec, media source can be 'filesystem' or 'camera' or 'camcorder'
Ben Murdoch8cad4132012-01-11 10:56:43 +0000295 // or 'microphone' and the default value should be 'filesystem'.
296 String mediaSource = mediaSourceValueFileSystem;
Michael Kolb8233fac2010-10-26 16:08:53 -0700297
Michael Kolb8233fac2010-10-26 16:08:53 -0700298 if (mUploadMessage != null) {
299 // Already a file picker operation in progress.
300 return;
301 }
302
303 mUploadMessage = uploadMsg;
304
305 // Parse the accept type.
306 String params[] = acceptType.split(";");
307 String mimeType = params[0];
308
Ben Murdoch8cad4132012-01-11 10:56:43 +0000309 if (capture.length() > 0) {
310 mediaSource = capture;
311 }
312
313 if (capture.equals(mediaSourceValueFileSystem)) {
314 // To maintain backwards compatibility with the previous implementation
315 // of the media capture API, if the value of the 'capture' attribute is
316 // "filesystem", we should examine the accept-type for a MIME type that
317 // may specify a different capture value.
318 for (String p : params) {
319 String[] keyValue = p.split("=");
320 if (keyValue.length == 2) {
321 // Process key=value parameters.
322 if (mediaSourceKey.equals(keyValue[0])) {
323 mediaSource = keyValue[1];
324 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700325 }
326 }
327 }
328
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000329 //Ensure it is not still set from a previous upload.
330 mCameraFilePath = null;
331
332 if (mimeType.equals(imageMimeType)) {
333 if (mediaSource.equals(mediaSourceValueCamera)) {
334 // Specified 'image/*' and requested the camera, so go ahead and launch the
335 // camera directly.
336 startActivity(createCameraIntent());
337 return;
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000338 } else {
Ben Murdoch8cad4132012-01-11 10:56:43 +0000339 // Specified just 'image/*', capture=filesystem, or an invalid capture parameter.
340 // In all these cases we show a traditional picker filetered on accept type
341 // so launch an intent for both the Camera and image/* OPENABLE.
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000342 Intent chooser = createChooserIntent(createCameraIntent());
343 chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
344 startActivity(chooser);
345 return;
346 }
347 } else if (mimeType.equals(videoMimeType)) {
348 if (mediaSource.equals(mediaSourceValueCamcorder)) {
349 // Specified 'video/*' and requested the camcorder, so go ahead and launch the
350 // camcorder directly.
351 startActivity(createCamcorderIntent());
352 return;
Ben Murdoch8cad4132012-01-11 10:56:43 +0000353 } else {
354 // Specified just 'video/*', capture=filesystem or an invalid capture parameter.
355 // In all these cases we show an intent for the traditional file picker, filtered
356 // on accept type so launch an intent for both camcorder and video/* OPENABLE.
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000357 Intent chooser = createChooserIntent(createCamcorderIntent());
358 chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
359 startActivity(chooser);
360 return;
361 }
362 } else if (mimeType.equals(audioMimeType)) {
363 if (mediaSource.equals(mediaSourceValueMicrophone)) {
364 // Specified 'audio/*' and requested microphone, so go ahead and launch the sound
365 // recorder.
366 startActivity(createSoundRecorderIntent());
367 return;
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000368 } else {
Ben Murdoch8cad4132012-01-11 10:56:43 +0000369 // Specified just 'audio/*', capture=filesystem of an invalid capture parameter.
370 // In all these cases so go ahead and launch an intent for both the sound
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000371 // recorder and audio/* OPENABLE.
372 Intent chooser = createChooserIntent(createSoundRecorderIntent());
373 chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
374 startActivity(chooser);
375 return;
376 }
377 }
378
379 // No special handling based on the accept type was necessary, so trigger the default
380 // file upload chooser.
381 startActivity(createDefaultOpenableIntent());
382 }
383
Vivek Sekharb54614f2014-05-01 19:03:37 -0700384 void showFileChooser(ValueCallback<String[]> uploadFilePaths, String acceptTypes,
385 boolean capture) {
386
387 final String imageMimeType = "image/*";
388 final String videoMimeType = "video/*";
389 final String audioMimeType = "audio/*";
390
391 if (mUploadFilePaths != null) {
392 // Already a file picker operation in progress.
393 return;
394 }
395
396 mUploadFilePaths = uploadFilePaths;
397
398 // Parse the accept type.
399 String params[] = acceptTypes.split(";");
400 String mimeType = params[0];
401
402 // Ensure it is not still set from a previous upload.
403 mCameraFilePath = null;
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700404 List<Intent> intentList = new ArrayList<Intent>();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700405
406 if (mimeType.equals(imageMimeType)) {
407 if (capture) {
408 // Specified 'image/*' and capture=true, so go ahead and launch the
409 // camera directly.
410 startActivity(createCameraIntent());
411 return;
412 } else {
413 // Specified just 'image/*', capture=false, or no capture value.
414 // In all these cases we show a traditional picker filetered on accept type
415 // so launch an intent for both the Camera and image/* OPENABLE.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700416 intentList.add(createCameraIntent());
417 createUploadDialog(imageMimeType, intentList);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700418 return;
419 }
420 } else if (mimeType.equals(videoMimeType)) {
421 if (capture) {
422 // Specified 'video/*' and capture=true, so go ahead and launch the
423 // camcorder directly.
424 startActivity(createCamcorderIntent());
425 return;
426 } else {
427 // Specified just 'video/*', capture=false, or no capture value.
428 // In all these cases we show an intent for the traditional file picker, filtered
429 // on accept type so launch an intent for both camcorder and video/* OPENABLE.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700430 intentList.add(createCamcorderIntent());
431 createUploadDialog(videoMimeType, intentList);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700432 return;
433 }
434 } else if (mimeType.equals(audioMimeType)) {
435 if (capture) {
436 // Specified 'audio/*' and capture=true, so go ahead and launch the sound
437 // recorder.
438 startActivity(createSoundRecorderIntent());
439 return;
440 } else {
441 // Specified just 'audio/*', capture=false, or no capture value.
442 // In all these cases so go ahead and launch an intent for both the sound
443 // recorder and audio/* OPENABLE.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700444 intentList.add(createSoundRecorderIntent());
445 createUploadDialog(audioMimeType, intentList);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700446 return;
447 }
448 }
449
450 // No special handling based on the accept type was necessary, so trigger the default
451 // file upload chooser.
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700452 createUploadDialog("*/*", null);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700453 }
454
455
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000456 private void startActivity(Intent intent) {
457 try {
458 mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
459 } catch (ActivityNotFoundException e) {
460 // No installed app was able to handle the intent that
461 // we sent, so fallback to the default file upload control.
462 try {
Ben Murdoch51f6a2f2011-02-21 12:27:07 +0000463 mCaughtActivityNotFoundException = true;
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000464 mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
465 Controller.FILE_SELECTED);
466 } catch (ActivityNotFoundException e2) {
467 // Nothing can return us a file, so file upload is effectively disabled.
468 Toast.makeText(mController.getActivity(), R.string.uploads_disabled,
469 Toast.LENGTH_LONG).show();
470 }
471 }
472 }
473
474 private Intent createDefaultOpenableIntent() {
475 // Create and return a chooser with the default OPENABLE
476 // actions including the camera, camcorder and sound
477 // recorder where available.
Michael Kolb8233fac2010-10-26 16:08:53 -0700478 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
479 i.addCategory(Intent.CATEGORY_OPENABLE);
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000480 i.setType("*/*");
Michael Kolb8233fac2010-10-26 16:08:53 -0700481
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000482 Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
483 createSoundRecorderIntent());
484 chooser.putExtra(Intent.EXTRA_INTENT, i);
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700485
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000486 return chooser;
487 }
488
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700489
490 private void createUploadDialog(String openableMimeType, List<Intent> intentList) {
491
492 Intent openable = new Intent(Intent.ACTION_GET_CONTENT);
493 openable.addCategory(Intent.CATEGORY_OPENABLE);
494 openable.setType(openableMimeType);
495
496 if (openableMimeType.equals("*/*") && intentList == null) {
497 intentList = new ArrayList<Intent>();
498 intentList.add(createCameraIntent());
499 intentList.add(createCamcorderIntent());
500 intentList.add(createSoundRecorderIntent());
501 }
502
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700503 PackageManager pm = mController.getActivity().getPackageManager();
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700504 ArrayList<ResolveInfo> uploadApps = new ArrayList<ResolveInfo>();
505
506 //Step 1:- resolve all apps for IntentList passed
Axesh R. Ajmeracdbedf12014-12-09 15:25:40 -0800507 for (Iterator<Intent> iterator = intentList.iterator(); iterator.hasNext();) {
508 List<ResolveInfo> intentAppsList = pm.queryIntentActivities(iterator.next(),
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700509 PackageManager.MATCH_DEFAULT_ONLY);
Axesh R. Ajmeracdbedf12014-12-09 15:25:40 -0800510
511 // Check whether any apps are available
512 if (intentAppsList!= null && intentAppsList.size() > 0){
513 // limit only to first activity
514 uploadApps.add(intentAppsList.get(0));
515 } else {
516 iterator.remove();
517 }
518
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700519 }
520
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700521 // Step 2:- get all openable apps list and create corresponding intents
522 List<ResolveInfo> openableAppsList = pm.queryIntentActivities(openable,
523 PackageManager.MATCH_DEFAULT_ONLY);
524 // limit only to first activity
525 ResolveInfo topOpenableApp = openableAppsList.get(0);
526 uploadApps.add(topOpenableApp);
527 ActivityInfo activityInfo = topOpenableApp.activityInfo;
528 ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,
529 activityInfo.name);
530 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
531 i.setType(openableMimeType);
532 i.setComponent(name);
533 intentList.add(i);
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700534
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700535 // Step 3: Pass all the apps and their corresponding intents to uploaddialog
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700536 UploadDialog upDialog = new UploadDialog(mController.getActivity());
Axesh R. Ajmera025fed32014-09-04 11:18:47 -0700537 upDialog.getUploadableApps(uploadApps, intentList);
Axesh R. Ajmera3aae1012014-07-03 16:37:53 -0700538 upDialog.loadView(this);
539 }
540
541 public void initiateActivity(Intent intent) {
542 startActivity(intent);
543 }
544
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000545 private Intent createChooserIntent(Intent... intents) {
546 Intent chooser = new Intent(Intent.ACTION_CHOOSER);
547 chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
548 chooser.putExtra(Intent.EXTRA_TITLE,
549 mController.getActivity().getResources()
550 .getString(R.string.choose_upload));
551 return chooser;
552 }
553
554 private Intent createOpenableIntent(String type) {
555 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
556 i.addCategory(Intent.CATEGORY_OPENABLE);
557 i.setType(type);
558 return i;
559 }
560
561 private Intent createCameraIntent() {
Michael Kolb8233fac2010-10-26 16:08:53 -0700562 Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
563 File externalDataDir = Environment.getExternalStoragePublicDirectory(
564 Environment.DIRECTORY_DCIM);
565 File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
566 File.separator + "browser-photos");
567 cameraDataDir.mkdirs();
568 mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
569 System.currentTimeMillis() + ".jpg";
570 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000571 return cameraIntent;
Michael Kolb8233fac2010-10-26 16:08:53 -0700572 }
573
Ben Murdoche4c0cae2011-02-18 11:25:38 +0000574 private Intent createCamcorderIntent() {
575 return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
576 }
577
578 private Intent createSoundRecorderIntent() {
579 return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
Michael Kolb8233fac2010-10-26 16:08:53 -0700580 }
581
582}