openEventsPlatformApp/plugins/cordova-plugin-camera/src/android/FileHelper.java
plugins/cordova-plugin-camera/src/android/FileHelper.javaRaw
1/*
2 Licensed to the Apache Software Foundation (ASF) under one
3 or more contributor license agreements. See the NOTICE file
4 distributed with this work for additional information
5 regarding copyright ownership. The ASF licenses this file
6 to you under the Apache License, Version 2.0 (the
7 "License"); you may not use this file except in compliance
8 with the License. You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing,
11 software distributed under the License is distributed on an
12 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 KIND, either express or implied. See the License for the
14 specific language governing permissions and limitations
15 under the License.
16 */
17package org.apache.cordova.camera;
18
19import android.annotation.SuppressLint;
20import android.content.ContentUris;
21import android.content.Context;
22import android.content.CursorLoader;
23import android.database.Cursor;
24import android.net.Uri;
25import android.os.Build;
26import android.os.Environment;
27import android.provider.DocumentsContract;
28import android.provider.MediaStore;
29import android.webkit.MimeTypeMap;
30
31import org.apache.cordova.CordovaInterface;
32import org.apache.cordova.LOG;
33
34import java.io.FileInputStream;
35import java.io.IOException;
36import java.io.InputStream;
37import java.util.Locale;
38
39public class FileHelper {
40 private static final String LOG_TAG = "FileUtils";
41 private static final String _DATA = "_data";
42
43 /**
44 * Returns the real path of the given URI string.
45 * If the given URI string represents a content:// URI, the real path is retrieved from the media store.
46 *
47 * @param uriString the URI string of the audio/image/video
48 * @param cordova the current application context
49 * @return the full path to the file
50 */
51 @SuppressWarnings("deprecation")
52 public static String getRealPath(Uri uri, CordovaInterface cordova) {
53 String realPath = null;
54
55 if (Build.VERSION.SDK_INT < 11)
56 realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri);
57
58 // SDK >= 11
59 else
60 realPath = FileHelper.getRealPathFromURI_API11_And_Above(cordova.getActivity(), uri);
61
62 return realPath;
63 }
64
65 /**
66 * Returns the real path of the given URI.
67 * If the given URI is a content:// URI, the real path is retrieved from the media store.
68 *
69 * @param uri the URI of the audio/image/video
70 * @param cordova the current application context
71 * @return the full path to the file
72 */
73 public static String getRealPath(String uriString, CordovaInterface cordova) {
74 return FileHelper.getRealPath(Uri.parse(uriString), cordova);
75 }
76
77 @SuppressLint("NewApi")
78 public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) {
79
80 final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
81 // DocumentProvider
82 if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
83
84 // ExternalStorageProvider
85 if (isExternalStorageDocument(uri)) {
86 final String docId = DocumentsContract.getDocumentId(uri);
87 final String[] split = docId.split(":");
88 final String type = split[0];
89
90 if ("primary".equalsIgnoreCase(type)) {
91 return Environment.getExternalStorageDirectory() + "/" + split[1];
92 }
93
94 // TODO handle non-primary volumes
95 }
96 // DownloadsProvider
97 else if (isDownloadsDocument(uri)) {
98
99 final String id = DocumentsContract.getDocumentId(uri);
100 final Uri contentUri = ContentUris.withAppendedId(
101 Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
102
103 return getDataColumn(context, contentUri, null, null);
104 }
105 // MediaProvider
106 else if (isMediaDocument(uri)) {
107 final String docId = DocumentsContract.getDocumentId(uri);
108 final String[] split = docId.split(":");
109 final String type = split[0];
110
111 Uri contentUri = null;
112 if ("image".equals(type)) {
113 contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
114 } else if ("video".equals(type)) {
115 contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
116 } else if ("audio".equals(type)) {
117 contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
118 }
119
120 final String selection = "_id=?";
121 final String[] selectionArgs = new String[] {
122 split[1]
123 };
124
125 return getDataColumn(context, contentUri, selection, selectionArgs);
126 }
127 }
128 // MediaStore (and general)
129 else if ("content".equalsIgnoreCase(uri.getScheme())) {
130
131 // Return the remote address
132 if (isGooglePhotosUri(uri))
133 return uri.getLastPathSegment();
134
135 return getDataColumn(context, uri, null, null);
136 }
137 // File
138 else if ("file".equalsIgnoreCase(uri.getScheme())) {
139 return uri.getPath();
140 }
141
142 return null;
143 }
144
145 public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
146 String[] proj = { MediaStore.Images.Media.DATA };
147 String result = null;
148
149 try {
150 Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
151 int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
152 cursor.moveToFirst();
153 result = cursor.getString(column_index);
154
155 } catch (Exception e) {
156 result = null;
157 }
158 return result;
159 }
160
161 /**
162 * Returns an input stream based on given URI string.
163 *
164 * @param uriString the URI string from which to obtain the input stream
165 * @param cordova the current application context
166 * @return an input stream into the data at the given URI or null if given an invalid URI string
167 * @throws IOException
168 */
169 public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova)
170 throws IOException {
171 InputStream returnValue = null;
172 if (uriString.startsWith("content")) {
173 Uri uri = Uri.parse(uriString);
174 returnValue = cordova.getActivity().getContentResolver().openInputStream(uri);
175 } else if (uriString.startsWith("file://")) {
176 int question = uriString.indexOf("?");
177 if (question > -1) {
178 uriString = uriString.substring(0, question);
179 }
180 if (uriString.startsWith("file:///android_asset/")) {
181 Uri uri = Uri.parse(uriString);
182 String relativePath = uri.getPath().substring(15);
183 returnValue = cordova.getActivity().getAssets().open(relativePath);
184 } else {
185 // might still be content so try that first
186 try {
187 returnValue = cordova.getActivity().getContentResolver().openInputStream(Uri.parse(uriString));
188 } catch (Exception e) {
189 returnValue = null;
190 }
191 if (returnValue == null) {
192 returnValue = new FileInputStream(getRealPath(uriString, cordova));
193 }
194 }
195 } else {
196 returnValue = new FileInputStream(uriString);
197 }
198 return returnValue;
199 }
200
201 /**
202 * Removes the "file://" prefix from the given URI string, if applicable.
203 * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
204 *
205 * @param uriString the URI string to operate on
206 * @return a path without the "file://" prefix
207 */
208 public static String stripFileProtocol(String uriString) {
209 if (uriString.startsWith("file://")) {
210 uriString = uriString.substring(7);
211 }
212 return uriString;
213 }
214
215 public static String getMimeTypeForExtension(String path) {
216 String extension = path;
217 int lastDot = extension.lastIndexOf('.');
218 if (lastDot != -1) {
219 extension = extension.substring(lastDot + 1);
220 }
221 // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
222 extension = extension.toLowerCase(Locale.getDefault());
223 if (extension.equals("3ga")) {
224 return "audio/3gpp";
225 }
226 return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
227 }
228
229 /**
230 * Returns the mime type of the data specified by the given URI string.
231 *
232 * @param uriString the URI string of the data
233 * @return the mime type of the specified data
234 */
235 public static String getMimeType(String uriString, CordovaInterface cordova) {
236 String mimeType = null;
237
238 Uri uri = Uri.parse(uriString);
239 if (uriString.startsWith("content://")) {
240 mimeType = cordova.getActivity().getContentResolver().getType(uri);
241 } else {
242 mimeType = getMimeTypeForExtension(uri.getPath());
243 }
244
245 return mimeType;
246 }
247
248 /**
249 * Get the value of the data column for this Uri. This is useful for
250 * MediaStore Uris, and other file-based ContentProviders.
251 *
252 * @param context The context.
253 * @param uri The Uri to query.
254 * @param selection (Optional) Filter used in the query.
255 * @param selectionArgs (Optional) Selection arguments used in the query.
256 * @return The value of the _data column, which is typically a file path.
257 * @author paulburke
258 */
259 public static String getDataColumn(Context context, Uri uri, String selection,
260 String[] selectionArgs) {
261
262 Cursor cursor = null;
263 final String column = "_data";
264 final String[] projection = {
265 column
266 };
267
268 try {
269 cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
270 null);
271 if (cursor != null && cursor.moveToFirst()) {
272
273 final int column_index = cursor.getColumnIndexOrThrow(column);
274 return cursor.getString(column_index);
275 }
276 } catch (Exception e) {
277 return null;
278 } finally {
279 if (cursor != null)
280 cursor.close();
281 }
282 return null;
283 }
284
285 /**
286 * @param uri The Uri to check.
287 * @return Whether the Uri authority is ExternalStorageProvider.
288 * @author paulburke
289 */
290 public static boolean isExternalStorageDocument(Uri uri) {
291 return "com.android.externalstorage.documents".equals(uri.getAuthority());
292 }
293
294 /**
295 * @param uri The Uri to check.
296 * @return Whether the Uri authority is DownloadsProvider.
297 * @author paulburke
298 */
299 public static boolean isDownloadsDocument(Uri uri) {
300 return "com.android.providers.downloads.documents".equals(uri.getAuthority());
301 }
302
303 /**
304 * @param uri The Uri to check.
305 * @return Whether the Uri authority is MediaProvider.
306 * @author paulburke
307 */
308 public static boolean isMediaDocument(Uri uri) {
309 return "com.android.providers.media.documents".equals(uri.getAuthority());
310 }
311
312 /**
313 * @param uri The Uri to check.
314 * @return Whether the Uri authority is Google Photos.
315 */
316 public static boolean isGooglePhotosUri(Uri uri) {
317 return "com.google.android.apps.photos.content".equals(uri.getAuthority());
318 }
319}