Compare commits

..

26 Commits
2.3.0 ... 2.3.x

Author SHA1 Message Date
Shazron Abdullah
35b98bd0f0 CB-12236 - Fixed RELEASENOTES for cordova-plugin-camera 2016-12-12 11:05:32 -08:00
Shazron Abdullah
9eba35e2f6 CB-12224 Updated version and RELEASENOTES.md for release 2.3.1 2016-12-07 16:39:43 -08:00
Shazron Abdullah
8b83171ee2 Fix missing license headers. 2016-12-07 16:19:39 -08:00
Vladimir Kotikov
c9e6a9a38a CB-12086 Regenerate README.md from template 2016-11-14 10:01:22 +03:00
Chris Rae
cc48945f37 Added NSPhotoLibraryUsageDescription parameter to example install command
Fixing some usages of NSPhotoLibraryUsageDescriptionentry

 This closes #240
2016-11-13 23:36:38 +01:00
Joe Bowser
8b3410bcc6 Close #124: I can crop fine with Photos. We should not have adopted Crop, since it makes no sense on Android. 2016-11-09 10:05:33 -08:00
Simon MacDonald
485a11e0f4 Updating compat dependency to 1.1.0 or better 2016-11-07 21:40:38 -05:00
Joe Bowser
2d47a26271 Close #199. We save photos to a shared Pictures directory, similar to the behaviour of the Twitter application 2016-11-07 16:23:16 -08:00
Joe Bowser
2d2352f695 Close #201. Running out of memory shouldn't be graceful. 2016-11-07 16:21:17 -08:00
Joe Bowser
2f003d2b49 Close #228. We don't require these permissions on Camera, since we use intents. 2016-11-07 16:19:00 -08:00
Joe Bowser
3a90bb7d55 Close #241 2016-11-07 16:11:45 -08:00
Joe Bowser
b13cbdeb16 Merge branch 'nougat_camera'
This closes #235
2016-11-07 15:59:20 -08:00
Joe Bowser
ee192d94b4 Bumping the CI 2016-11-07 15:49:52 -08:00
Joe Bowser
d9eb83bcb9 CB-11625: Forgot to add CordovaUri.java to plugin.xml 2016-10-27 13:38:46 -07:00
Joe Bowser
84f96c1067 CB-11625: Files Provider does not work with Android 4.4.4 or lower, and I have no idea why. Working around with CordovaUri 2016-10-27 13:37:03 -07:00
Joe Bowser
61064ae3ed CB-11625 (Android) : Make this work with previous versions of Cordova via cordova-plugin-compat 2016-10-21 15:12:34 -07:00
Shazron Abdullah
9ec8aea073 CB-11917 - Remove pull request template checklist item: "iCLA has been submitted…"
This closes #237
2016-10-04 21:39:29 -07:00
Julio César
9db952e161 Closing invalid pull request: close #98 2016-09-24 00:47:37 +02:00
Steve Gill
06d609cfa4 CB-11832 Incremented plugin version. 2016-09-09 16:08:02 -07:00
Joe Bowser
b63a0d83e0 Merging API 24 code with master including large refactor 2016-09-01 15:11:33 -07:00
Joe Bowser
3ed3d887ca BuildConfig from test project crept in source code thanks to Android Studio, removing 2016-08-04 11:35:39 -07:00
Joe Bowser
f010394af8 WTF. Directory, not file. Not sure why I did that 2016-08-04 11:16:29 -07:00
Joe Bowser
00e0a7dc46 CB-11625: Managed to get Content Providers to work with a weird mix of Content Providers and non-Content Providers 2016-08-03 14:43:11 -07:00
Joe Bowser
b62fdf50f7 Adding provider_paths.xml so this works 2016-07-29 13:33:51 -07:00
Joe Bowser
744d72a33b Partially modified plugin.xml 2016-07-29 09:07:03 -07:00
Joe Bowser
3d26986bfd CB-11625: Working on fix to API 24 no longer allowing File URIs to be passed across intents 2016-07-27 14:06:07 -07:00
10 changed files with 298 additions and 98 deletions

View File

@@ -17,7 +17,6 @@ Thanks!
### Checklist
- [ ] [ICLA](http://www.apache.org/licenses/icla.txt) has been signed and submitted to secretary@apache.org.
- [ ] [Reported an issue](http://cordova.apache.org/contribute/issues.html) in the JIRA database
- [ ] Commit message follows the format: "CB-3232: (android) Fix bug with resolving file paths", where CB-xxxx is the JIRA ID & "android" is the platform affected.
- [ ] Added automated test coverage as appropriate for this change.

View File

@@ -76,21 +76,21 @@ Documentation consists of template and API docs produced from the plugin JS code
### iOS Quirks
Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` and `NSPhotoLibraryUsageDescriptionentry` in the info.plist.
Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` and `NSPhotoLibraryUsageDescription` in the info.plist.
- `NSCameraUsageDescription` describes the reason that the app accesses the users camera.
- `NSPhotoLibraryUsageDescriptionentry` describes the reason the app accesses the user's photo library.
- `NSPhotoLibraryUsageDescription` describes the reason the app accesses the user's photo library.
When the system prompts the user to allow access, this string is displayed as part of the dialog box.
To add this entry you can pass the following variables on plugin install.
- `CAMERA_USAGE_DESCRIPTION` for `NSCameraUsageDescription`
- `PHOTOLIBRARY_USAGE_DESCRIPTION` for `NSPhotoLibraryUsageDescriptionentry`
-
- `PHOTOLIBRARY_USAGE_DESCRIPTION` for `NSPhotoLibraryUsageDescription`
Example:
cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="your usage message"
cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="your usage message" --variable PHOTOLIBRARY_USAGE_DESCRIPTION="your usage message"
If you don't pass the variable, the plugin will add an empty string as value.

View File

@@ -20,6 +20,21 @@
-->
# Release Notes
### 2.3.1 (Dec 07, 2016)
* [CB-12224](https://issues.apache.org/jira/browse/CB-12224) Updated version and RELEASENOTES.md for release 2.3.1
* Fix missing license headers.
* [CB-12086](https://issues.apache.org/jira/browse/CB-12086) Regenerate README.md from template
* Added NSPhotoLibraryUsageDescription parameter to example install command Fixing some usages of NSPhotoLibraryUsageDescriptionentry
* Updating compat dependency to 1.1.0 or better
* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Forgot to add CordovaUri.java to plugin.xml
* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Files Provider does not work with Android 4.4.4 or lower, and I have no idea why. Working around with CordovaUri
* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) (Android) : Make this work with previous versions of Cordova via cordova-plugin-compat
* BuildConfig from test project crept in source code thanks to Android Studio, removing
* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Managed to get Content Providers to work with a weird mix of Content Providers and non-Content Providers
* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Working on fix to API 24 no longer allowing File URIs to be passed across intents
* [CB-11917](https://issues.apache.org/jira/browse/CB-11917) - Remove pull request template checklist item: "iCLA has been submitted…"
* [CB-11832](https://issues.apache.org/jira/browse/CB-11832) Incremented plugin version.
### 2.3.0 (Sep 08, 2016)
* [CB-11795](https://issues.apache.org/jira/browse/CB-11795) Add 'protective' entry to cordovaDependencies
* [CB-11661](https://issues.apache.org/jira/browse/CB-11661) Add mandatory **iOS 10** privacy description

View File

@@ -18,21 +18,21 @@ the system's image library.
### iOS Quirks
Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` and `NSPhotoLibraryUsageDescriptionentry` in the info.plist.
Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` and `NSPhotoLibraryUsageDescription` in the info.plist.
- `NSCameraUsageDescription` describes the reason that the app accesses the users camera.
- `NSPhotoLibraryUsageDescriptionentry` describes the reason the app accesses the user's photo library.
- `NSPhotoLibraryUsageDescription` describes the reason the app accesses the user's photo library.
When the system prompts the user to allow access, this string is displayed as part of the dialog box.
To add this entry you can pass the following variables on plugin install.
- `CAMERA_USAGE_DESCRIPTION` for `NSCameraUsageDescription`
- `PHOTOLIBRARY_USAGE_DESCRIPTION` for `NSPhotoLibraryUsageDescriptionentry`
-
- `PHOTOLIBRARY_USAGE_DESCRIPTION` for `NSPhotoLibraryUsageDescription`
Example:
cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="your usage message"
cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="your usage message" --variable PHOTOLIBRARY_USAGE_DESCRIPTION="your usage message"
If you don't pass the variable, the plugin will add an empty string as value.

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-camera",
"version": "2.3.0",
"version": "2.3.1",
"description": "Cordova Camera Plugin",
"cordova": {
"id": "cordova-plugin-camera",

View File

@@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rim="http://www.blackberry.com/ns/widgets"
id="cordova-plugin-camera"
version="2.3.0">
version="2.3.1">
<name>Camera</name>
<description>Cordova Camera Plugin</description>
<license>Apache 2.0</license>
@@ -30,7 +30,7 @@
<repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git</repo>
<issue>https://issues.apache.org/jira/browse/CB/component/12320645</issue>
<dependency id="cordova-plugin-compat" version="^1.0.0" />
<dependency id="cordova-plugin-compat" version="^1.1.0" />
<js-module src="www/CameraConstants.js" name="Camera">
<clobbers target="Camera" />
@@ -69,16 +69,31 @@
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</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/CordovaUri.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/xml/provider_paths.xml" target-dir="res/xml" />
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
<clobbers target="CameraPopoverHandle" />
</js-module>
</js-module>
</platform>
<framework src="com.android.support:support-v4:24.1.1+" />
</platform>
<!-- amazon-fireos -->
<platform name="amazon-fireos">

View File

@@ -29,8 +29,10 @@ import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.cordova.BuildHelper;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.LOG;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
@@ -58,6 +60,8 @@ import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.support.v4.content.FileProvider;
import android.util.Base64;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -99,7 +103,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
private int targetWidth; // desired width of the image
private int targetHeight; // desired height of the image
private Uri imageUri; // Uri of captured image
private CordovaUri imageUri; // Uri of captured image
private int encodingType; // Type of encoding to use
private int mediaType; // What type of media to retrieve
private int destType; // Source type (needs to be saved for the permission handling)
@@ -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 croppedUri;
private ExifHelper exifData; // Exif data from source
private String applicationId;
/**
@@ -130,6 +135,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
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) BuildHelper.getBuildConfigValue(cordova.getActivity(), "APPLICATION_ID");
this.applicationId = preferences.getString("applicationId", this.applicationId);
if (action.equals("takePicture")) {
this.srcType = CAMERA;
@@ -232,7 +242,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
* img.src=result;
*
* @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) {
boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
@@ -282,8 +292,12 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// Specify file so that large image is captured and returned
File photo = createCaptureFile(encodingType);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
this.imageUri = Uri.fromFile(photo);
this.imageUri = new CordovaUri(FileProvider.getUriForFile(cordova.getActivity(),
applicationId + ".provider",
photo));
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageUri.getCorrectUri());
//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) {
// Let's check to make sure the camera is actually installed. (Legacy Nexus 7 code)
@@ -399,33 +413,37 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
*/
private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
// indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
// set crop properties
cropIntent.putExtra("crop", "true");
Intent cropIntent = new Intent("com.android.camera.action.CROP");
// indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
// set crop properties
cropIntent.putExtra("crop", "true");
// indicate output X and Y
if (targetWidth > 0) {
// indicate output X and Y
if (targetWidth > 0) {
cropIntent.putExtra("outputX", targetWidth);
}
if (targetHeight > 0) {
}
if (targetHeight > 0) {
cropIntent.putExtra("outputY", targetHeight);
}
if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
}
if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
}
// create new file handle to get full resolution crop
croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
cropIntent.putExtra("output", croppedUri);
}
// create new file handle to get full resolution crop
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);
// start the activity - we handle returning in onActivityResult
if (this.cordova != null) {
this.cordova.startActivityForResult((CordovaPlugin) this,
cropIntent, CROP_CAMERA + destType);
}
// start the activity - we handle returning in onActivityResult
if (this.cordova != null) {
this.cordova.startActivityForResult((CordovaPlugin) this,
cropIntent, CROP_CAMERA + destType);
}
} catch (ActivityNotFoundException anfe) {
LOG.e(LOG_TAG, "Crop operation not supported on this device");
try {
@@ -450,9 +468,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper();
String sourcePath = (this.allowEdit && this.croppedUri != null) ?
FileHelper.stripFileProtocol(this.croppedUri.toString()) :
FileHelper.stripFileProtocol(this.imageUri.toString());
FileHelper.stripFileProtocol(this.croppedUri.toString()) :
this.imageUri.getFilePath();
if (this.encodingType == JPEG) {
try {
@@ -475,10 +495,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
if (this.saveToPhotoAlbum) {
galleryUri = Uri.fromFile(new File(getPicturesPath()));
if(this.allowEdit && this.croppedUri != null) {
writeUncompressedImage(this.croppedUri, galleryUri);
if (this.allowEdit && this.croppedUri != null) {
writeUncompressedImage(croppedUri, galleryUri);
} else {
writeUncompressedImage(this.imageUri, galleryUri);
Uri imageUri = this.imageUri.getFileUri();
writeUncompressedImage(imageUri, galleryUri);
}
refreshGallery(galleryUri);
@@ -490,7 +511,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
if (bitmap == null) {
// Try to get the bitmap from intent.
bitmap = (Bitmap)intent.getExtras().get("data");
bitmap = (Bitmap) intent.getExtras().get("data");
}
// Double-check the bitmap.
@@ -521,10 +542,12 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
} else {
Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
if(this.allowEdit && this.croppedUri != null) {
writeUncompressedImage(this.croppedUri, uri);
if (this.allowEdit && this.croppedUri != null) {
Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri)));
writeUncompressedImage(croppedUri, uri);
} else {
writeUncompressedImage(this.imageUri, uri);
Uri imageUri = this.imageUri.getFileUri();
writeUncompressedImage(imageUri, uri);
}
this.callbackContext.success(uri.toString());
@@ -566,12 +589,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
throw new IllegalStateException();
}
this.cleanup(FILE_URI, this.imageUri, galleryUri, bitmap);
this.cleanup(FILE_URI, this.imageUri.getFileUri(), galleryUri, bitmap);
bitmap = null;
}
private String getPicturesPath()
{
private String getPicturesPath() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
File storageDir = Environment.getExternalStoragePublicDirectory(
@@ -580,8 +602,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
return galleryPath;
}
private void refreshGallery(Uri contentUri)
{
private void refreshGallery(Uri contentUri) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(contentUri);
this.cordova.getActivity().sendBroadcast(mediaScanIntent);
@@ -601,9 +622,16 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
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 fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
//String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
String modifiedPath = getTempDirectoryPath() + "/" + fileName;
OutputStream os = new FileOutputStream(modifiedPath);
@@ -630,12 +658,11 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
/**
* Applies all needed transformation to the image received from the gallery.
*
* @param destType In which form should we return the image
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
* @param destType In which form should we return the image
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
private void processResultFromGallery(int destType, Intent intent) {
Uri uri = intent.getData();
@@ -710,8 +737,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
e.printStackTrace();
this.failPicture("Error retrieving image.");
}
}
else {
} else {
this.callbackContext.success(fileLocation);
}
}
@@ -727,10 +753,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
/**
* Called when the camera view exits.
*
* @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
* @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
@@ -767,12 +793,12 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// If image available
if (resultCode == Activity.RESULT_OK) {
try {
if(this.allowEdit)
{
Uri tmpFile = Uri.fromFile(createCaptureFile(this.encodingType));
if (this.allowEdit) {
Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
applicationId + ".provider",
createCaptureFile(this.encodingType));
performCrop(tmpFile, destType, intent);
}
else {
} else {
this.processResultFromCamera(destType, intent);
}
} catch (IOException e) {
@@ -801,11 +827,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
processResultFromGallery(finalDestType, i);
}
});
}
else if (resultCode == Activity.RESULT_CANCELED) {
} else if (resultCode == Activity.RESULT_CANCELED) {
this.failPicture("Selection cancelled.");
}
else {
} else {
this.failPicture("Selection did not complete!");
}
}
@@ -847,14 +871,14 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
try {
os.close();
} catch (IOException e) {
LOG.d(LOG_TAG,"Exception while closing output stream.");
LOG.d(LOG_TAG, "Exception while closing output stream.");
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
LOG.d(LOG_TAG,"Exception while closing file input stream.");
LOG.d(LOG_TAG, "Exception while closing file input stream.");
}
}
}
@@ -918,7 +942,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
try {
fileStream.close();
} catch (IOException e) {
LOG.d(LOG_TAG,"Exception while closing file input stream.");
LOG.d(LOG_TAG, "Exception while closing file input stream.");
}
}
}
@@ -1126,8 +1150,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
* @return
*/
public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
final float srcAspect = (float) srcWidth / (float) srcHeight;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect > dstAspect) {
return srcWidth / dstWidth;
@@ -1144,7 +1168,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private Cursor queryImgDB(Uri contentStore) {
return this.cordova.getActivity().getContentResolver().query(
contentStore,
new String[] { MediaStore.Images.Media._ID },
new String[]{MediaStore.Images.Media._ID},
null,
null,
null);
@@ -1152,6 +1176,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
/**
* Cleans up after picture taking. Checking for duplicates and that kind of stuff.
*
* @param newImage
*/
private void cleanup(int imageType, Uri oldImage, Uri newImage, Bitmap bitmap) {
@@ -1203,6 +1228,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
/**
* Determine if we are storing the images in internal or external storage
*
* @return Uri
*/
private Uri whichContentStore() {
@@ -1251,7 +1277,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private void scanForGallery(Uri newImage) {
this.scanMe = newImage;
if(this.conn != null) {
if (this.conn != null) {
this.conn.disconnect();
}
this.conn = new MediaScannerConnection(this.cordova.getActivity().getApplicationContext(), this);
@@ -1259,9 +1285,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
public void onMediaScannerConnected() {
try{
try {
this.conn.scanFile(this.scanMe.toString(), "image/*");
} catch (java.lang.IllegalStateException e){
} catch (java.lang.IllegalStateException e) {
LOG.e(LOG_TAG, "Can't scan file in MediaScanner after taking picture");
}
@@ -1273,18 +1299,14 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
public void onRequestPermissionResult(int requestCode, String[] permissions,
int[] grantResults) throws JSONException
{
for(int r:grantResults)
{
if(r == PackageManager.PERMISSION_DENIED)
{
int[] grantResults) throws JSONException {
for (int r : grantResults) {
if (r == PackageManager.PERMISSION_DENIED) {
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
return;
}
}
switch(requestCode)
{
switch (requestCode) {
case TAKE_PIC_SEC:
takePicture(this.destType, this.encodingType);
break;
@@ -1313,12 +1335,12 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
state.putBoolean("correctOrientation", this.correctOrientation);
state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum);
if(this.croppedUri != null) {
if (this.croppedUri != null) {
state.putString("croppedUri", this.croppedUri.toString());
}
if(this.imageUri != null) {
state.putString("imageUri", this.imageUri.toString());
if (this.imageUri != null) {
state.putString("imageUri", this.imageUri.getFileUri().toString());
}
return state;
@@ -1337,14 +1359,38 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
this.correctOrientation = state.getBoolean("correctOrientation");
this.saveToPhotoAlbum = state.getBoolean("saveToPhotoAlbum");
if(state.containsKey("croppedUri")) {
if (state.containsKey("croppedUri")) {
this.croppedUri = Uri.parse(state.getString("croppedUri"));
}
if(state.containsKey("imageUri")) {
this.imageUri = Uri.parse(state.getString("imageUri"));
if (state.containsKey("imageUri")) {
//I have no idea what type of URI is being passed in
this.imageUri = new CordovaUri(Uri.parse(state.getString("imageUri")));
}
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;
}
}

104
src/android/CordovaUri.java Normal file
View File

@@ -0,0 +1,104 @@
/*
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 org.apache.cordova.camera;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import java.io.File;
/*
* This class exists because Andorid FilesProvider doesn't work on Android 4.4.4 and below and throws
* weird errors. I'm not sure why writing to shared cache directories is somehow verboten, but it is
* and this error is irritating for a Compatibility library to have.
*
*/
public class CordovaUri {
private Uri androidUri;
private String fileName;
private Uri fileUri;
/*
* We always expect a FileProvider string to be passed in for the file that we create
*
*/
CordovaUri (Uri inputUri)
{
//Determine whether the file is a content or file URI
if(inputUri.getScheme().equals("content"))
{
androidUri = inputUri;
fileName = getFileNameFromUri(androidUri);
fileUri = Uri.parse("file://" + fileName);
}
else
{
fileUri = inputUri;
fileName = FileHelper.stripFileProtocol(inputUri.toString());
}
}
public Uri getFileUri()
{
return fileUri;
}
public String getFilePath()
{
return fileName;
}
/*
* This only gets called by takePicture
*/
public Uri getCorrectUri()
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
return androidUri;
else
return fileUri;
}
/*
* 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;
}
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

View File

@@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rim="http://www.blackberry.com/ns/widgets"
id="cordova-plugin-camera-tests"
version="2.3.0">
version="2.3.1">
<name>Cordova Camera Plugin Tests</name>
<license>Apache 2.0</license>