diff --git a/package.json b/package.json index d517d6d..fdd791a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-mediapicker-dmcsdk", - "version": "2.4.2", + "version": "2.4.3", "description": "android ios mediaPicker support selection of multiple image and video", "cordova": { "id": "cordova-plugin-mediapicker-dmcsdk", diff --git a/plugin.xml b/plugin.xml index b423439..4b3a09c 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,6 +1,6 @@ - + MediaPicker @@ -19,6 +19,7 @@ + diff --git a/src/android/FileHelper.java b/src/android/FileHelper.java new file mode 100644 index 0000000..1d85272 --- /dev/null +++ b/src/android/FileHelper.java @@ -0,0 +1,317 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package com.dmc.mediaPickerPlugin; + +import android.annotation.SuppressLint; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; +import android.webkit.MimeTypeMap; + +import org.apache.cordova.CordovaInterface; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +public class FileHelper { + private static final String LOG_TAG = "FileUtils"; + private static final String _DATA = "_data"; + + /** + * Returns the real path of the given URI string. + * If the given URI string represents a content:// URI, the real path is retrieved from the media store. + * + * @param uriString the URI string of the audio/image/video + * @param cordova the current application context + * @return the full path to the file + */ + @SuppressWarnings("deprecation") + public static String getRealPath(Uri uri, CordovaInterface cordova) { + String realPath = null; + + if (Build.VERSION.SDK_INT < 11) + realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri); + + // SDK >= 11 + else + realPath = FileHelper.getRealPathFromURI_API11_And_Above(cordova.getActivity(), uri); + + return realPath; + } + + /** + * Returns the real path of the given URI. + * If the given URI is a content:// URI, the real path is retrieved from the media store. + * + * @param uri the URI of the audio/image/video + * @param cordova the current application context + * @return the full path to the file + */ + public static String getRealPath(String uriString, CordovaInterface cordova) { + return FileHelper.getRealPath(Uri.parse(uriString), cordova); + } + + @SuppressLint("NewApi") + public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) { + + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + + // TODO handle non-primary volumes + } + // DownloadsProvider + else if (isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + + return getDataColumn(context, contentUri, null, null); + } + // MediaProvider + else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + + // Return the remote address + if (isGooglePhotosUri(uri)) + return uri.getLastPathSegment(); + + return getDataColumn(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + return null; + } + + public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) { + String[] proj = { MediaStore.Images.Media.DATA }; + String result = null; + + try { + Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null); + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + result = cursor.getString(column_index); + + } catch (Exception e) { + result = null; + } + return result; + } + + /** + * Returns an input stream based on given URI string. + * + * @param uriString the URI string from which to obtain the input stream + * @param cordova the current application context + * @return an input stream into the data at the given URI or null if given an invalid URI string + * @throws IOException + */ + public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova) + throws IOException { + InputStream returnValue = null; + if (uriString.startsWith("content")) { + Uri uri = Uri.parse(uriString); + returnValue = cordova.getActivity().getContentResolver().openInputStream(uri); + } else if (uriString.startsWith("file://")) { + int question = uriString.indexOf("?"); + if (question > -1) { + uriString = uriString.substring(0, question); + } + if (uriString.startsWith("file:///android_asset/")) { + Uri uri = Uri.parse(uriString); + String relativePath = uri.getPath().substring(15); + returnValue = cordova.getActivity().getAssets().open(relativePath); + } else { + // might still be content so try that first + try { + returnValue = cordova.getActivity().getContentResolver().openInputStream(Uri.parse(uriString)); + } catch (Exception e) { + returnValue = null; + } + if (returnValue == null) { + returnValue = new FileInputStream(getRealPath(uriString, cordova)); + } + } + } else { + returnValue = new FileInputStream(uriString); + } + return returnValue; + } + + /** + * Removes the "file://" prefix from the given URI string, if applicable. + * If the given URI string doesn't have a "file://" prefix, it is returned unchanged. + * + * @param uriString the URI string to operate on + * @return a path without the "file://" prefix + */ + public static String stripFileProtocol(String uriString) { + if (uriString.startsWith("file://")) { + uriString = uriString.substring(7); + } + return uriString; + } + + public static String getMimeTypeForExtension(String path) { + String extension = path; + int lastDot = extension.lastIndexOf('.'); + if (lastDot != -1) { + extension = extension.substring(lastDot + 1); + } + // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185). + extension = extension.toLowerCase(Locale.getDefault()); + if (extension.equals("3ga")) { + return "audio/3gpp"; + } + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } + + /** + * Returns the mime type of the data specified by the given URI string. + * + * @param uriString the URI string of the data + * @return the mime type of the specified data + */ + public static String getMimeType(String uriString, CordovaInterface cordova) { + String mimeType = null; + + Uri uri = Uri.parse(uriString); + if (uriString.startsWith("content://")) { + mimeType = cordova.getActivity().getContentResolver().getType(uri); + } else { + mimeType = getMimeTypeForExtension(uri.getPath()); + } + + return mimeType; + } + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + * @author paulburke + */ + public static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, + null); + if (cursor != null && cursor.moveToFirst()) { + + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } catch (Exception e) { + return null; + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + * @author paulburke + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + * @author paulburke + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + * @author paulburke + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is Google Photos. + */ + public static boolean isGooglePhotosUri(Uri uri) { + return "com.google.android.apps.photos.content".equals(uri.getAuthority()); + } +} diff --git a/src/android/MediaPicker.java b/src/android/MediaPicker.java index 33a22ce..ad971dc 100644 --- a/src/android/MediaPicker.java +++ b/src/android/MediaPicker.java @@ -1,22 +1,21 @@ package com.dmc.mediaPickerPlugin; -import android.app.ProgressDialog; -import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.media.ThumbnailUtils; +import android.net.Uri; import android.provider.MediaStore; import android.util.Base64; -import android.net.Uri; import android.util.Log; import com.dmcbig.mediapicker.PickerActivity; import com.dmcbig.mediapicker.PickerConfig; -import com.dmcbig.mediapicker.entity.Media; import com.dmcbig.mediapicker.TakePhotoActivity; +import com.dmcbig.mediapicker.entity.Media; + import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; import org.json.JSONArray; @@ -28,6 +27,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; @@ -66,6 +66,9 @@ public class MediaPicker extends CordovaPlugin { }else if(action.equals("getExifForKey")){ this.getExifForKey(args.getString(0),args.getString(1),callbackContext); return true; + }else if(action.equals("getFileInfo")){ + this.getFileInfo(args,callbackContext); + return true; } return false; } @@ -250,6 +253,31 @@ public class MediaPicker extends CordovaPlugin { } } + public void getFileInfo( JSONArray args, CallbackContext callbackContext){ + this.callback=callbackContext; + try { + String type=args.getString(1); + File file; + if("uri".equals(type)){ + file=new File(FileHelper.getRealPath(args.getString(0),cordova)); + }else{ + file=new File(args.getString(0)); + } + JSONObject jsonObject=new JSONObject(); + jsonObject.put("path", file.getPath()); + jsonObject.put("uri", Uri.fromFile(new File(file.getPath()))); + jsonObject.put("size", file.length()); + jsonObject.put("name", file.getName()); + String mimeType = FileHelper.getMimeType(jsonObject.getString("uri"),cordova); + String mediaType = mimeType.indexOf("video")!=-1?"video":"image"; + jsonObject.put("mediaType",mediaType); + callbackContext.success(jsonObject); + } catch (Exception e) { + callbackContext.error("getFileInfo error"+e); + e.printStackTrace(); + } + } + public File compressImage(String path,int quality){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); String compFileName="dmcMediaPickerCompress"+System.currentTimeMillis()+".jpg"; diff --git a/src/ios/MediaPicker.m b/src/ios/MediaPicker.m index d6f12a7..fe4f941 100644 --- a/src/ios/MediaPicker.m +++ b/src/ios/MediaPicker.m @@ -321,5 +321,51 @@ [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:result]callbackId:command.callbackId]; } +- (void)getFileInfo:(CDVInvokedUrlCommand*)command +{ + callbackId=command.callbackId; + NSString *type= [command.arguments objectAtIndex: 1]; + NSURL *url; + NSString *path; + if([type isEqualToString:@"uri"]){ + NSString *str=[command.arguments objectAtIndex: 0]; + url = [NSURL URLWithString:str]; + path= url.path; + }else{ + path= [command.arguments objectAtIndex: 0]; + url = [NSURL fileURLWithPath:path]; + } + NSMutableDictionary *options = [NSMutableDictionary dictionaryWithCapacity:5]; + [options setObject:path forKey:@"path"]; + [options setObject:url.absoluteString forKey:@"uri"]; + + NSNumber * size = [NSNumber numberWithUnsignedLongLong:[[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileSize]]; + [options setObject:size forKey:@"size"]; + NSString *fileName = [[NSFileManager defaultManager] displayNameAtPath:path]; + [options setObject:fileName forKey:@"name"]; + if([[self getMIMETypeURLRequestAtPath:path] containsString:@"video"]){ + [options setObject:@"video" forKey:@"mediaType"]; + }else{ + [options setObject:@"image" forKey:@"mediaType"]; + } + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:options] callbackId:callbackId]; +} + + +-(NSString *)getMIMETypeURLRequestAtPath:(NSString*)path +{ + //1.确定请求路径 + NSURL *url = [NSURL fileURLWithPath:path]; + + //2.创建可变的请求对象 + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + //3.发送请求 + NSHTTPURLResponse *response = nil; + [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; + + NSString *mimeType = response.MIMEType; + return mimeType; +} @end diff --git a/www/MediaPicker.js b/www/MediaPicker.js index c9becfe..ae61de3 100644 --- a/www/MediaPicker.js +++ b/www/MediaPicker.js @@ -8,8 +8,14 @@ var MediaPicker = { photoLibrary:function(arg0, success, error) { exec(success, error, "MediaPicker", "photoLibrary", [arg0]); }, - takePhoto:function(arg0, success, error) { - exec(success, error, "MediaPicker", "takePhoto", [arg0]); + takePhoto:function(success, error, cameraOptions) { + cameraOptions.destinationType= Camera.DestinationType.FILE_URI; //only support FILE_URI + navigator.camera.getPicture(function(arg0){ + MediaPicker.getFileInfo(arg0,"uri", function(media) { + success(media); + }, function(e) { console.log(e) }); }, function(arg1){ + error(arg1); + }, cameraOptions); }, extractThumbnail:function(arg0, success, error) { exec(success, error, "MediaPicker", "extractThumbnail", [arg0]); @@ -26,8 +32,11 @@ var MediaPicker = { fileToBlob:function(arg0, success, error) { exec(success, error, "MediaPicker", "fileToBlob", [arg0]); }, - getExifForKey:function(arg0,arg1, success, error) { + getExifForKey:function(arg0, arg1, success, error) { exec(success, error, "MediaPicker", "getExifForKey", [arg0,arg1]); + }, + getFileInfo:function(path, argType, success, error) { //type:"path" or "uri" + exec(success, error, "MediaPicker", "getFileInfo", [path,argType]); } };