summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/values/strings.xml3
-rw-r--r--src/com/android/browser/UploadHandler.java179
2 files changed, 109 insertions, 73 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b61385a..8005e14 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -18,6 +18,9 @@
<string name="application_name">Browser</string>
<!-- Displayed with a file picker to choose a file to upload -->
<string name="choose_upload">Choose file for upload</string>
+ <!-- Toast to show the user after they try to open the file picker but no apps on the
+ system can provide a file [CHAR-LIMIT=NONE]-->
+ <string name="uploads_disabled">File uploads are disabled.</string>
<!-- Name of menu item of a new tab. Also used in the title bar when displaying a new tab -->
<string name="new_tab">New window</string>
<!-- Name of menu item of a new incognito tab. Also used in the
diff --git a/src/com/android/browser/UploadHandler.java b/src/com/android/browser/UploadHandler.java
index d9b387f..ee578fa 100644
--- a/src/com/android/browser/UploadHandler.java
+++ b/src/com/android/browser/UploadHandler.java
@@ -17,11 +17,13 @@
package com.android.browser;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.webkit.ValueCallback;
+import android.widget.Toast;
import java.io.File;
import java.util.Vector;
@@ -82,14 +84,10 @@ public class UploadHandler {
final String mediaSourceValueCamcorder = "camcorder";
final String mediaSourceValueMicrophone = "microphone";
- // media source can be 'filesystem' or 'camera' or 'camcorder' or 'microphone'.
+ // According to the spec, media source can be 'filesystem' or 'camera' or 'camcorder'
+ // or 'microphone'.
String mediaSource = "";
- // We add the camera intent if there was no accept type (or '*/*' or 'image/*').
- boolean addCameraIntent = true;
- // We add the camcorder intent if there was no accept type (or '*/*' or 'video/*').
- boolean addCamcorderIntent = true;
-
if (mUploadMessage != null) {
// Already a file picker operation in progress.
return;
@@ -111,104 +109,139 @@ public class UploadHandler {
}
}
- // This intent will display the standard OPENABLE file picker.
- Intent i = new Intent(Intent.ACTION_GET_CONTENT);
- i.addCategory(Intent.CATEGORY_OPENABLE);
-
- // Create an intent to add to the standard file picker that will
- // capture an image from the camera. We'll combine this intent with
- // the standard OPENABLE picker unless the web developer specifically
- // requested the camera or gallery be opened by passing a parameter
- // in the accept type.
- Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- File externalDataDir = Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DCIM);
- File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
- File.separator + "browser-photos");
- cameraDataDir.mkdirs();
- mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
- System.currentTimeMillis() + ".jpg";
- cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
-
- Intent camcorderIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
-
- Intent soundRecIntent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
+ //Ensure it is not still set from a previous upload.
+ mCameraFilePath = null;
if (mimeType.equals(imageMimeType)) {
- i.setType(imageMimeType);
- addCamcorderIntent = false;
if (mediaSource.equals(mediaSourceValueCamera)) {
- // Specified 'image/*' and requested the camera, so go ahead and launch the camera
- // directly.
- startActivity(cameraIntent);
+ // Specified 'image/*' and requested the camera, so go ahead and launch the
+ // camera directly.
+ startActivity(createCameraIntent());
return;
} else if (mediaSource.equals(mediaSourceValueFileSystem)) {
- // Specified filesytem as the source, so don't want to consider the camera.
- addCameraIntent = false;
+ // Specified 'image/*' and requested the filesystem, so go ahead and launch an
+ // OPENABLE intent.
+ startActivity(createOpenableIntent(imageMimeType));
+ return;
+ } else {
+ // Specified just 'image/*', so launch an intent for both the Camera and image/*
+ // OPENABLE.
+ Intent chooser = createChooserIntent(createCameraIntent());
+ chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
+ startActivity(chooser);
+ return;
}
} else if (mimeType.equals(videoMimeType)) {
- i.setType(videoMimeType);
- addCameraIntent = false;
- // The camcorder saves it's own file and returns it to us in the intent, so
- // we don't need to generate one here.
- mCameraFilePath = null;
-
if (mediaSource.equals(mediaSourceValueCamcorder)) {
// Specified 'video/*' and requested the camcorder, so go ahead and launch the
// camcorder directly.
- startActivity(camcorderIntent);
+ startActivity(createCamcorderIntent());
return;
} else if (mediaSource.equals(mediaSourceValueFileSystem)) {
- // Specified filesystem as the source, so don't want to consider the camcorder.
- addCamcorderIntent = false;
+ // Specified 'video/*' and requested the filesystem, so go ahead and launch an
+ // an OPENABLE intent.
+ startActivity(createOpenableIntent(videoMimeType));
+ return;
+ } else {
+ // Specified just 'video/*', so go ahead and launch an intent for both camcorder and
+ // video/* OPENABLE.
+ Intent chooser = createChooserIntent(createCamcorderIntent());
+ chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
+ startActivity(chooser);
+ return;
}
} else if (mimeType.equals(audioMimeType)) {
- i.setType(audioMimeType);
- addCameraIntent = false;
- addCamcorderIntent = false;
if (mediaSource.equals(mediaSourceValueMicrophone)) {
// Specified 'audio/*' and requested microphone, so go ahead and launch the sound
// recorder.
- startActivity(soundRecIntent);
+ startActivity(createSoundRecorderIntent());
+ return;
+ } else if (mediaSource.equals(mediaSourceValueFileSystem)) {
+ // Specified 'audio/*' and requested filesystem, so go ahead and launch an
+ // OPENABLE intent.
+ startActivity(createOpenableIntent(audioMimeType));
+ return;
+ } else {
+ // Specified just 'audio/*', so go ahead and launch an intent for both the sound
+ // recorder and audio/* OPENABLE.
+ Intent chooser = createChooserIntent(createSoundRecorderIntent());
+ chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
+ startActivity(chooser);
return;
}
- // On a default system, there is no single option to open an audio "gallery". Both the
- // sound recorder and music browser respond to the OPENABLE/audio/* intent unlike the
- // image/* and video/* OPENABLE intents where the image / video gallery are the only
- // respondants (and so the user is not prompted by default).
- } else {
- i.setType("*/*");
}
- // Combine the chooser and the extra choices (like camera or camcorder)
- Intent chooser = new Intent(Intent.ACTION_CHOOSER);
- chooser.putExtra(Intent.EXTRA_INTENT, i);
-
- Vector<Intent> extraInitialIntents = new Vector<Intent>(0);
+ // No special handling based on the accept type was necessary, so trigger the default
+ // file upload chooser.
+ startActivity(createDefaultOpenableIntent());
+ }
- if (addCameraIntent) {
- extraInitialIntents.add(cameraIntent);
+ private void startActivity(Intent intent) {
+ try {
+ mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
+ } catch (ActivityNotFoundException e) {
+ // No installed app was able to handle the intent that
+ // we sent, so fallback to the default file upload control.
+ try {
+ mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
+ Controller.FILE_SELECTED);
+ } catch (ActivityNotFoundException e2) {
+ // Nothing can return us a file, so file upload is effectively disabled.
+ Toast.makeText(mController.getActivity(), R.string.uploads_disabled,
+ Toast.LENGTH_LONG).show();
+ }
}
+ }
- if (addCamcorderIntent) {
- extraInitialIntents.add(camcorderIntent);
- }
+ private Intent createDefaultOpenableIntent() {
+ // Create and return a chooser with the default OPENABLE
+ // actions including the camera, camcorder and sound
+ // recorder where available.
+ Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+ i.addCategory(Intent.CATEGORY_OPENABLE);
+ i.setType("*/*");
- if (extraInitialIntents.size() > 0) {
- Intent[] extraIntents = new Intent[extraInitialIntents.size()];
- chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,
- extraInitialIntents.toArray(extraIntents));
- }
+ Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
+ createSoundRecorderIntent());
+ chooser.putExtra(Intent.EXTRA_INTENT, i);
+ return chooser;
+ }
+ private Intent createChooserIntent(Intent... intents) {
+ Intent chooser = new Intent(Intent.ACTION_CHOOSER);
+ chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
chooser.putExtra(Intent.EXTRA_TITLE,
mController.getActivity().getResources()
.getString(R.string.choose_upload));
- startActivity(chooser);
+ return chooser;
}
- private void startActivity(Intent intent) {
- mController.getActivity().startActivityForResult(intent,
- Controller.FILE_SELECTED);
+ private Intent createOpenableIntent(String type) {
+ Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+ i.addCategory(Intent.CATEGORY_OPENABLE);
+ i.setType(type);
+ return i;
+ }
+
+ private Intent createCameraIntent() {
+ Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ File externalDataDir = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DCIM);
+ File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
+ File.separator + "browser-photos");
+ cameraDataDir.mkdirs();
+ mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
+ System.currentTimeMillis() + ".jpg";
+ cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
+ return cameraIntent;
+ }
+
+ private Intent createCamcorderIntent() {
+ return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+ }
+
+ private Intent createSoundRecorderIntent() {
+ return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
}
}