mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2025-01-31 12:42:50 +08:00
Merging API 24 code with master including large refactor
This commit is contained in:
commit
b63a0d83e0
14
plugin.xml
14
plugin.xml
@ -69,15 +69,29 @@
|
|||||||
<config-file target="AndroidManifest.xml" parent="/*">
|
<config-file target="AndroidManifest.xml" parent="/*">
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
</config-file>
|
</config-file>
|
||||||
|
<config-file target="AndroidManifest.xml" parent="application">
|
||||||
|
<provider
|
||||||
|
android:name="android.support.v4.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.provider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true" >
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/provider_paths"/>
|
||||||
|
</provider>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
<source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
<source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
<source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
|
<source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
|
||||||
|
<source-file src="src/android/xml/provider_paths.xml" target-dir="res/xml" />
|
||||||
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
||||||
<clobbers target="CameraPopoverHandle" />
|
<clobbers target="CameraPopoverHandle" />
|
||||||
</js-module>
|
</js-module>
|
||||||
|
|
||||||
|
<framework src="com.android.support:support-v4:24.1.1+" />
|
||||||
|
|
||||||
</platform>
|
</platform>
|
||||||
|
|
||||||
<!-- amazon-fireos -->
|
<!-- amazon-fireos -->
|
||||||
|
@ -31,6 +31,8 @@ import java.util.Date;
|
|||||||
|
|
||||||
import org.apache.cordova.CallbackContext;
|
import org.apache.cordova.CallbackContext;
|
||||||
import org.apache.cordova.CordovaPlugin;
|
import org.apache.cordova.CordovaPlugin;
|
||||||
|
import org.apache.cordova.CordovaResourceApi;
|
||||||
|
import org.apache.cordova.CoreAndroid;
|
||||||
import org.apache.cordova.LOG;
|
import org.apache.cordova.LOG;
|
||||||
import org.apache.cordova.PermissionHelper;
|
import org.apache.cordova.PermissionHelper;
|
||||||
import org.apache.cordova.PluginResult;
|
import org.apache.cordova.PluginResult;
|
||||||
@ -58,6 +60,8 @@ import android.os.Bundle;
|
|||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
import android.provider.OpenableColumns;
|
||||||
|
import android.support.v4.content.FileProvider;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
@ -118,6 +122,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
private Uri scanMe; // Uri of image to be added to content store
|
private Uri scanMe; // Uri of image to be added to content store
|
||||||
private Uri croppedUri;
|
private Uri croppedUri;
|
||||||
private ExifHelper exifData; // Exif data from source
|
private ExifHelper exifData; // Exif data from source
|
||||||
|
private String applicationId;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,6 +135,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
*/
|
*/
|
||||||
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
||||||
this.callbackContext = callbackContext;
|
this.callbackContext = callbackContext;
|
||||||
|
//Adding an API to CoreAndroid to get the BuildConfigValue
|
||||||
|
//This allows us to not make this a breaking change to embedding
|
||||||
|
this.applicationId = (String) CoreAndroid.getBuildConfigValue(cordova.getActivity(), "APPLICATION_ID");
|
||||||
|
|
||||||
|
|
||||||
if (action.equals("takePicture")) {
|
if (action.equals("takePicture")) {
|
||||||
this.srcType = CAMERA;
|
this.srcType = CAMERA;
|
||||||
@ -232,7 +241,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
* img.src=result;
|
* img.src=result;
|
||||||
*
|
*
|
||||||
* @param returnType Set the type of image to return.
|
* @param returnType Set the type of image to return.
|
||||||
* @param encodingType JPEG or PNG
|
* @param encodingType Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
||||||
*/
|
*/
|
||||||
public void callTakePicture(int returnType, int encodingType) {
|
public void callTakePicture(int returnType, int encodingType) {
|
||||||
boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
|
boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
@ -282,8 +291,12 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
// Specify file so that large image is captured and returned
|
// Specify file so that large image is captured and returned
|
||||||
File photo = createCaptureFile(encodingType);
|
File photo = createCaptureFile(encodingType);
|
||||||
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
|
this.imageUri = FileProvider.getUriForFile(cordova.getActivity(),
|
||||||
this.imageUri = Uri.fromFile(photo);
|
applicationId + ".provider",
|
||||||
|
photo);
|
||||||
|
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, this.imageUri);
|
||||||
|
//We can write to this URI, this will hopefully allow us to write files to get to the next step
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
|
||||||
if (this.cordova != null) {
|
if (this.cordova != null) {
|
||||||
// Let's check to make sure the camera is actually installed. (Legacy Nexus 7 code)
|
// Let's check to make sure the camera is actually installed. (Legacy Nexus 7 code)
|
||||||
@ -405,6 +418,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
// set crop properties
|
// set crop properties
|
||||||
cropIntent.putExtra("crop", "true");
|
cropIntent.putExtra("crop", "true");
|
||||||
|
|
||||||
|
|
||||||
// indicate output X and Y
|
// indicate output X and Y
|
||||||
if (targetWidth > 0) {
|
if (targetWidth > 0) {
|
||||||
cropIntent.putExtra("outputX", targetWidth);
|
cropIntent.putExtra("outputX", targetWidth);
|
||||||
@ -418,8 +432,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
}
|
}
|
||||||
// create new file handle to get full resolution crop
|
// create new file handle to get full resolution crop
|
||||||
croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
||||||
|
cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
cropIntent.putExtra("output", croppedUri);
|
cropIntent.putExtra("output", croppedUri);
|
||||||
|
|
||||||
|
|
||||||
// start the activity - we handle returning in onActivityResult
|
// start the activity - we handle returning in onActivityResult
|
||||||
|
|
||||||
if (this.cordova != null) {
|
if (this.cordova != null) {
|
||||||
@ -450,9 +467,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
// Create an ExifHelper to save the exif data that is lost during compression
|
// Create an ExifHelper to save the exif data that is lost during compression
|
||||||
ExifHelper exif = new ExifHelper();
|
ExifHelper exif = new ExifHelper();
|
||||||
|
|
||||||
String sourcePath = (this.allowEdit && this.croppedUri != null) ?
|
String sourcePath = (this.allowEdit && this.croppedUri != null) ?
|
||||||
FileHelper.stripFileProtocol(this.croppedUri.toString()) :
|
FileHelper.stripFileProtocol(this.croppedUri.toString()) :
|
||||||
FileHelper.stripFileProtocol(this.imageUri.toString());
|
getFileNameFromUri(this.imageUri);
|
||||||
|
|
||||||
|
|
||||||
if (this.encodingType == JPEG) {
|
if (this.encodingType == JPEG) {
|
||||||
try {
|
try {
|
||||||
@ -476,9 +495,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
galleryUri = Uri.fromFile(new File(getPicturesPath()));
|
galleryUri = Uri.fromFile(new File(getPicturesPath()));
|
||||||
|
|
||||||
if (this.allowEdit && this.croppedUri != null) {
|
if (this.allowEdit && this.croppedUri != null) {
|
||||||
writeUncompressedImage(this.croppedUri, galleryUri);
|
writeUncompressedImage(croppedUri, galleryUri);
|
||||||
} else {
|
} else {
|
||||||
writeUncompressedImage(this.imageUri, galleryUri);
|
Uri imageUri = Uri.fromFile(new File(getFileNameFromUri(this.imageUri)));
|
||||||
|
writeUncompressedImage(imageUri, galleryUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshGallery(galleryUri);
|
refreshGallery(galleryUri);
|
||||||
@ -522,9 +542,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
|
||||||
|
|
||||||
if (this.allowEdit && this.croppedUri != null) {
|
if (this.allowEdit && this.croppedUri != null) {
|
||||||
writeUncompressedImage(this.croppedUri, uri);
|
Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri)));
|
||||||
|
writeUncompressedImage(croppedUri, uri);
|
||||||
} else {
|
} else {
|
||||||
writeUncompressedImage(this.imageUri, uri);
|
Uri imageUri = Uri.fromFile(new File(getFileNameFromUri(this.imageUri)));
|
||||||
|
writeUncompressedImage(imageUri, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callbackContext.success(uri.toString());
|
this.callbackContext.success(uri.toString());
|
||||||
@ -570,8 +592,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
bitmap = null;
|
bitmap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPicturesPath()
|
private String getPicturesPath() {
|
||||||
{
|
|
||||||
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
||||||
String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
|
String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
|
||||||
File storageDir = Environment.getExternalStoragePublicDirectory(
|
File storageDir = Environment.getExternalStoragePublicDirectory(
|
||||||
@ -580,8 +601,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
return galleryPath;
|
return galleryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshGallery(Uri contentUri)
|
private void refreshGallery(Uri contentUri) {
|
||||||
{
|
|
||||||
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||||
mediaScanIntent.setData(contentUri);
|
mediaScanIntent.setData(contentUri);
|
||||||
this.cordova.getActivity().sendBroadcast(mediaScanIntent);
|
this.cordova.getActivity().sendBroadcast(mediaScanIntent);
|
||||||
@ -601,9 +621,16 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
|
|
||||||
private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException {
|
private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException {
|
||||||
|
// Some content: URIs do not map to file paths (e.g. picasa).
|
||||||
|
String realPath = FileHelper.getRealPath(uri, this.cordova);
|
||||||
|
|
||||||
|
// Get filename from uri
|
||||||
|
String fileName = realPath != null ?
|
||||||
|
realPath.substring(realPath.lastIndexOf('/') + 1) :
|
||||||
|
"modified." + (this.encodingType == JPEG ? "jpg" : "png");
|
||||||
|
|
||||||
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
||||||
String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
|
//String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
|
||||||
String modifiedPath = getTempDirectoryPath() + "/" + fileName;
|
String modifiedPath = getTempDirectoryPath() + "/" + fileName;
|
||||||
|
|
||||||
OutputStream os = new FileOutputStream(modifiedPath);
|
OutputStream os = new FileOutputStream(modifiedPath);
|
||||||
@ -630,7 +657,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies all needed transformation to the image received from the gallery.
|
* Applies all needed transformation to the image received from the gallery.
|
||||||
*
|
*
|
||||||
@ -710,8 +736,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
this.failPicture("Error retrieving image.");
|
this.failPicture("Error retrieving image.");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.callbackContext.success(fileLocation);
|
this.callbackContext.success(fileLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -767,12 +792,12 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
// If image available
|
// If image available
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
try {
|
try {
|
||||||
if(this.allowEdit)
|
if (this.allowEdit) {
|
||||||
{
|
Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
|
||||||
Uri tmpFile = Uri.fromFile(createCaptureFile(this.encodingType));
|
applicationId + ".provider",
|
||||||
|
createCaptureFile(this.encodingType));
|
||||||
performCrop(tmpFile, destType, intent);
|
performCrop(tmpFile, destType, intent);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.processResultFromCamera(destType, intent);
|
this.processResultFromCamera(destType, intent);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -801,11 +826,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
processResultFromGallery(finalDestType, i);
|
processResultFromGallery(finalDestType, i);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
} else if (resultCode == Activity.RESULT_CANCELED) {
|
||||||
else if (resultCode == Activity.RESULT_CANCELED) {
|
|
||||||
this.failPicture("Selection cancelled.");
|
this.failPicture("Selection cancelled.");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.failPicture("Selection did not complete!");
|
this.failPicture("Selection did not complete!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1152,6 +1175,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up after picture taking. Checking for duplicates and that kind of stuff.
|
* Cleans up after picture taking. Checking for duplicates and that kind of stuff.
|
||||||
|
*
|
||||||
* @param newImage
|
* @param newImage
|
||||||
*/
|
*/
|
||||||
private void cleanup(int imageType, Uri oldImage, Uri newImage, Bitmap bitmap) {
|
private void cleanup(int imageType, Uri oldImage, Uri newImage, Bitmap bitmap) {
|
||||||
@ -1203,6 +1227,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if we are storing the images in internal or external storage
|
* Determine if we are storing the images in internal or external storage
|
||||||
|
*
|
||||||
* @return Uri
|
* @return Uri
|
||||||
*/
|
*/
|
||||||
private Uri whichContentStore() {
|
private Uri whichContentStore() {
|
||||||
@ -1273,18 +1298,14 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
|
|
||||||
public void onRequestPermissionResult(int requestCode, String[] permissions,
|
public void onRequestPermissionResult(int requestCode, String[] permissions,
|
||||||
int[] grantResults) throws JSONException
|
int[] grantResults) throws JSONException {
|
||||||
{
|
for (int r : grantResults) {
|
||||||
for(int r:grantResults)
|
if (r == PackageManager.PERMISSION_DENIED) {
|
||||||
{
|
|
||||||
if(r == PackageManager.PERMISSION_DENIED)
|
|
||||||
{
|
|
||||||
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
|
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch(requestCode)
|
switch (requestCode) {
|
||||||
{
|
|
||||||
case TAKE_PIC_SEC:
|
case TAKE_PIC_SEC:
|
||||||
takePicture(this.destType, this.encodingType);
|
takePicture(this.destType, this.encodingType);
|
||||||
break;
|
break;
|
||||||
@ -1347,4 +1368,26 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
|
|||||||
|
|
||||||
this.callbackContext = callbackContext;
|
this.callbackContext = callbackContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is dirty, but it does the job.
|
||||||
|
*
|
||||||
|
* Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
|
||||||
|
* and since we actually need the Camera to create the file for us most of the time, we don't
|
||||||
|
* actually write the file, just generate the location based on a timestamp, we need to get it
|
||||||
|
* back from the Intent.
|
||||||
|
*
|
||||||
|
* However, the FilesProvider preserves the path, so we can at least write to it from here, since
|
||||||
|
* we own the context in this case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
private String getFileNameFromUri(Uri uri) {
|
||||||
|
String fullUri = uri.toString();
|
||||||
|
String partial_path = fullUri.split("external_files")[1];
|
||||||
|
File external_storage = Environment.getExternalStorageDirectory();
|
||||||
|
String path = external_storage.getAbsolutePath() + partial_path;
|
||||||
|
return path;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
4
src/android/xml/provider_paths.xml
Normal file
4
src/android/xml/provider_paths.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<external-path name="external_files" path="."/>
|
||||||
|
</paths>
|
Loading…
Reference in New Issue
Block a user