blob: d9b387fbf5456bd556837e11420b34bf985e0d25 [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
17package com.android.browser;
18
19import android.app.Activity;
20import android.content.Intent;
21import android.net.Uri;
22import android.os.Environment;
23import android.provider.MediaStore;
24import android.webkit.ValueCallback;
25
26import java.io.File;
27import java.util.Vector;
28
29/**
30 * Handle the file upload callbacks from WebView here
31 */
32public class UploadHandler {
33
34 /*
35 * The Object used to inform the WebView of the file to upload.
36 */
37 private ValueCallback<Uri> mUploadMessage;
38 private String mCameraFilePath;
39
40 private Controller mController;
41
42 public UploadHandler(Controller controller) {
43 mController = controller;
44 }
45
46 String getFilePath() {
47 return mCameraFilePath;
48 }
49
50 void onResult(int resultCode, Intent intent) {
51 Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
52 : intent.getData();
53
54 // As we ask the camera to save the result of the user taking
55 // a picture, the camera application does not return anything other
56 // than RESULT_OK. So we need to check whether the file we expected
57 // was written to disk in the in the case that we
58 // did not get an intent returned but did get a RESULT_OK. If it was,
59 // we assume that this result has came back from the camera.
60 if (result == null && intent == null && resultCode == Activity.RESULT_OK) {
61 File cameraFile = new File(mCameraFilePath);
62 if (cameraFile.exists()) {
63 result = Uri.fromFile(cameraFile);
64 // Broadcast to the media scanner that we have a new photo
65 // so it will be added into the gallery for the user.
66 mController.getActivity().sendBroadcast(
67 new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
68 }
69 }
70
71 mUploadMessage.onReceiveValue(result);
72 }
73
74 void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
75
76 final String imageMimeType = "image/*";
77 final String videoMimeType = "video/*";
78 final String audioMimeType = "audio/*";
79 final String mediaSourceKey = "capture";
80 final String mediaSourceValueCamera = "camera";
81 final String mediaSourceValueFileSystem = "filesystem";
82 final String mediaSourceValueCamcorder = "camcorder";
83 final String mediaSourceValueMicrophone = "microphone";
84
85 // media source can be 'filesystem' or 'camera' or 'camcorder' or 'microphone'.
86 String mediaSource = "";
87
88 // We add the camera intent if there was no accept type (or '*/*' or 'image/*').
89 boolean addCameraIntent = true;
90 // We add the camcorder intent if there was no accept type (or '*/*' or 'video/*').
91 boolean addCamcorderIntent = true;
92
93 if (mUploadMessage != null) {
94 // Already a file picker operation in progress.
95 return;
96 }
97
98 mUploadMessage = uploadMsg;
99
100 // Parse the accept type.
101 String params[] = acceptType.split(";");
102 String mimeType = params[0];
103
104 for (String p : params) {
105 String[] keyValue = p.split("=");
106 if (keyValue.length == 2) {
107 // Process key=value parameters.
108 if (mediaSourceKey.equals(keyValue[0])) {
109 mediaSource = keyValue[1];
110 }
111 }
112 }
113
114 // This intent will display the standard OPENABLE file picker.
115 Intent i = new Intent(Intent.ACTION_GET_CONTENT);
116 i.addCategory(Intent.CATEGORY_OPENABLE);
117
118 // Create an intent to add to the standard file picker that will
119 // capture an image from the camera. We'll combine this intent with
120 // the standard OPENABLE picker unless the web developer specifically
121 // requested the camera or gallery be opened by passing a parameter
122 // in the accept type.
123 Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
124 File externalDataDir = Environment.getExternalStoragePublicDirectory(
125 Environment.DIRECTORY_DCIM);
126 File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
127 File.separator + "browser-photos");
128 cameraDataDir.mkdirs();
129 mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
130 System.currentTimeMillis() + ".jpg";
131 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
132
133 Intent camcorderIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
134
135 Intent soundRecIntent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
136
137 if (mimeType.equals(imageMimeType)) {
138 i.setType(imageMimeType);
139 addCamcorderIntent = false;
140 if (mediaSource.equals(mediaSourceValueCamera)) {
141 // Specified 'image/*' and requested the camera, so go ahead and launch the camera
142 // directly.
143 startActivity(cameraIntent);
144 return;
145 } else if (mediaSource.equals(mediaSourceValueFileSystem)) {
146 // Specified filesytem as the source, so don't want to consider the camera.
147 addCameraIntent = false;
148 }
149 } else if (mimeType.equals(videoMimeType)) {
150 i.setType(videoMimeType);
151 addCameraIntent = false;
152 // The camcorder saves it's own file and returns it to us in the intent, so
153 // we don't need to generate one here.
154 mCameraFilePath = null;
155
156 if (mediaSource.equals(mediaSourceValueCamcorder)) {
157 // Specified 'video/*' and requested the camcorder, so go ahead and launch the
158 // camcorder directly.
159 startActivity(camcorderIntent);
160 return;
161 } else if (mediaSource.equals(mediaSourceValueFileSystem)) {
162 // Specified filesystem as the source, so don't want to consider the camcorder.
163 addCamcorderIntent = false;
164 }
165 } else if (mimeType.equals(audioMimeType)) {
166 i.setType(audioMimeType);
167 addCameraIntent = false;
168 addCamcorderIntent = false;
169 if (mediaSource.equals(mediaSourceValueMicrophone)) {
170 // Specified 'audio/*' and requested microphone, so go ahead and launch the sound
171 // recorder.
172 startActivity(soundRecIntent);
173 return;
174 }
175 // On a default system, there is no single option to open an audio "gallery". Both the
176 // sound recorder and music browser respond to the OPENABLE/audio/* intent unlike the
177 // image/* and video/* OPENABLE intents where the image / video gallery are the only
178 // respondants (and so the user is not prompted by default).
179 } else {
180 i.setType("*/*");
181 }
182
183 // Combine the chooser and the extra choices (like camera or camcorder)
184 Intent chooser = new Intent(Intent.ACTION_CHOOSER);
185 chooser.putExtra(Intent.EXTRA_INTENT, i);
186
187 Vector<Intent> extraInitialIntents = new Vector<Intent>(0);
188
189 if (addCameraIntent) {
190 extraInitialIntents.add(cameraIntent);
191 }
192
193 if (addCamcorderIntent) {
194 extraInitialIntents.add(camcorderIntent);
195 }
196
197 if (extraInitialIntents.size() > 0) {
198 Intent[] extraIntents = new Intent[extraInitialIntents.size()];
199 chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,
200 extraInitialIntents.toArray(extraIntents));
201 }
202
203 chooser.putExtra(Intent.EXTRA_TITLE,
204 mController.getActivity().getResources()
205 .getString(R.string.choose_upload));
206 startActivity(chooser);
207 }
208
209 private void startActivity(Intent intent) {
210 mController.getActivity().startActivityForResult(intent,
211 Controller.FILE_SELECTED);
212 }
213
214}