Compare commits

..

34 Commits
0.2.1 ... 0.2.5

Author SHA1 Message Date
Steven Gill
0d94289921 [CB-5565] Updated version and RELEASENOTES.md for release 0.2.5 2013-12-04 15:16:30 -08:00
James Long
3424ddb39c fix camera for firefox os 2013-12-03 13:10:25 -08:00
Piotr Zalewa
e8e420895e getPicture via web activities 2013-12-03 13:09:27 -08:00
Steven Gill
a6736cda71 added ubuntu support 2013-12-02 15:11:12 -08:00
Maxim Ermilov
885c6a7459 [ubuntu] specify policy_group 2013-11-11 17:59:22 +04:00
Archana Naik
d8a3d2ff3a 1. User Agent detection now detects AmazonWebView.
2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'
2013-10-30 11:49:00 -07:00
Archana Naik
4590f2597c Added amazon-fireos platform. 2013-10-30 11:49:00 -07:00
Steven Gill
7c35f56a0d CB-5188: 2013-10-28 12:27:13 -07:00
Steven Gill
e0176cc61e [CB-5188] Updated version and RELEASENOTES.md for release 0.2.4 2013-10-28 10:58:16 -07:00
Maxim Ermilov
b44ea1c69f add ubuntu platform 2013-10-26 06:17:04 +04:00
hermwong
703f6c68d8 CB-5128: added repo + issue tag to plugin.xml for camera plugin 2013-10-21 15:33:45 -07:00
Shazron Abdullah
4e6cf5cc2e CB-4958 - iOS - Camera plugin should not show the status bar 2013-10-15 10:29:54 -07:00
hermwong
eab4822ae9 [CB-4919] updated plugin.xml for FxOS 2013-10-08 10:49:02 -07:00
Steven Gill
a600de41eb [CB-4915] Incremented plugin version on dev branch. 2013-09-25 18:34:12 -07:00
Steven Gill
fed4f2280d [CB-4915] Updated version and RELEASENOTES.md for release 0.2.3 2013-09-25 16:55:49 -07:00
Anis Kadri
c42bfe881f CB-4889 bumping&resetting version 2013-09-25 17:49:48 +02:00
Anis Kadri
200d6833f9 CB-4889 forgot index.html 2013-09-25 15:39:02 +02:00
Anis Kadri
6a1a558e81 CB-4889 renaming core inside cameraProxy 2013-09-25 15:34:11 +02:00
Anis Kadri
6a9949bb8c Merge branch 'dev' of https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera into dev 2013-09-25 15:03:03 +02:00
purplecabbage
f5a521f5ea [Windows8] commandProxy has moved 2013-09-25 15:02:30 +02:00
Anis Kadri
ed86de0d2a CB-4889 2013-09-25 15:02:03 +02:00
purplecabbage
363d139653 [Windows8] commandProxy has moved 2013-09-24 01:26:11 -07:00
Anis Kadri
809a23ffae CB-4889 renaming org.apache.cordova.core.camera to org.apache.cordova.camera 2013-09-21 12:03:08 +02:00
Herm Wong
3a3bbb1cc9 added Camera API for FirefoxOS 2013-09-18 16:22:13 -07:00
Andrew Grieve
8077d302fe Rename CHANGELOG.md -> RELEASENOTES.md 2013-09-17 11:36:13 -04:00
James Jong
9bcf725e39 [CB-4823] Fix XCode 5 camera plugin warnings 2013-09-16 15:13:35 -04:00
Andrew Grieve
224e7cfb20 Fix compiler warnings 2013-09-09 16:21:30 -04:00
Andrew Grieve
bc32c501da [CB-4765] Move ExifHelper.java into Camera Plugin 2013-09-09 16:15:16 -04:00
Andrew Grieve
df028dd257 [CB-4764] Remove reference to DirectoryManager from CameraLauncher 2013-09-09 16:10:16 -04:00
Andrew Grieve
44517ea93f [CB-4763] Use a copy of FileHelper.java within camera-plugin. 2013-09-09 15:10:40 -04:00
Andrew Grieve
8c77ddb864 [CB-4752] Incremented plugin version on dev branch. 2013-09-06 00:58:21 -04:00
Andrew Grieve
a9546c4f49 Merge branch 'dev' of https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera into dev 2013-09-06 00:22:17 -04:00
Joe Bowser
f33e00083a CB-4633: We really should close cursors. It's just the right thing to do. 2013-09-04 11:34:13 -07:00
Joe Bowser
118ca18d5a No longer causes a stack trace, but it doesn't cause the error to be called. 2013-09-04 11:34:13 -07:00
21 changed files with 955 additions and 66 deletions

View File

@@ -1,25 +0,0 @@
<!--
#
# 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.
#
-->
# Release Notes
### 0.2.1 (Sept 5, 2013)
* [CB-4656] Don't add line-breaks to base64-encoded images (Fixes type=DataURI)
* [CB-4432] copyright notice change

57
RELEASENOTES.md Normal file
View File

@@ -0,0 +1,57 @@
<!--
#
# 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.
#
-->
# Release Notes
### 0.2.1 (Sept 5, 2013)
* [CB-4656] Don't add line-breaks to base64-encoded images (Fixes type=DataURI)
* [CB-4432] copyright notice change
### 0.2.3 (Sept 25, 2013)
* CB-4889 bumping&resetting version
* CB-4889 forgot index.html
* CB-4889 renaming core inside cameraProxy
* [Windows8] commandProxy has moved
* [Windows8] commandProxy has moved
* added Camera API for FirefoxOS
* Rename CHANGELOG.md -> RELEASENOTES.md
* [CB-4823] Fix XCode 5 camera plugin warnings
* Fix compiler warnings
* [CB-4765] Move ExifHelper.java into Camera Plugin
* [CB-4764] Remove reference to DirectoryManager from CameraLauncher
* [CB-4763] Use a copy of FileHelper.java within camera-plugin.
* [CB-4752] Incremented plugin version on dev branch.
* CB-4633: We really should close cursors. It's just the right thing to do.
* No longer causes a stack trace, but it doesn't cause the error to be called.
* CB-4889 renaming org.apache.cordova.core.camera to org.apache.cordova.camera
### 0.2.4 (Oct 28, 2013)
* CB-5128: added repo + issue tag to plugin.xml for camera plugin
* CB-4958 - iOS - Camera plugin should not show the status bar
* [CB-4919] updated plugin.xml for FxOS
* [CB-4915] Incremented plugin version on dev branch.
### 0.2.5 (Dec 4, 2013)
* fix camera for firefox os
* getPicture via web activities
* [ubuntu] specify policy_group
* add ubuntu platform
* 1. User Agent detection now detects AmazonWebView. 2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'
* Added amazon-fireos platform.

View File

@@ -2,12 +2,14 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.core.camera"
version="0.2.1">
id="org.apache.cordova.camera"
version="0.2.5">
<name>Camera</name>
<description>Cordova Camera Plugin</description>
<license>Apache 2.0</license>
<keywords>cordova,camera</keywords>
<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>
<js-module src="www/CameraConstants.js" name="Camera">
<clobbers target="Camera" />
@@ -23,6 +25,18 @@
<clobbers target="navigator.camera" />
</js-module>
<!-- firefoxos -->
<platform name="firefoxos">
<config-file target="config.xml" parent="/*">
<feature name="Camera">
<param name="firefoxos-package" value="Camera" />
</feature>
</config-file>
<js-module src="src/firefoxos/camera.js" name="camera-impl">
<runs />
</js-module>
</platform>
<!-- android -->
<platform name="android">
<config-file target="res/xml/config.xml" parent="/*">
@@ -35,6 +49,8 @@
</config-file>
<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/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
<clobbers target="CameraPopoverHandle" />
@@ -42,6 +58,48 @@
</platform>
<!-- amazon-fireos -->
<platform name="amazon-fireos">
<config-file target="res/xml/config.xml" parent="/*">
<feature name="Camera">
<param name="android-package" value="org.apache.cordova.camera.CameraLauncher"/>
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
<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/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
<clobbers target="CameraPopoverHandle" />
</js-module>
</platform>
<!-- ubuntu -->
<platform name="ubuntu">
<config-file target="config.xml" parent="/*">
<feature name="Camera">
<param policy_group="camera" policy_version="1" />
</feature>
</config-file>
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
<clobbers target="CameraPopoverHandle" />
</js-module>
<header-file src="src/ubuntu/camera.h" />
<source-file src="src/ubuntu/camera.cpp" />
<resource-file src="src/ubuntu/back.png" />
<resource-file src="src/ubuntu/CaptureWidget.qml" />
<resource-file src="src/ubuntu/shoot.png" />
<resource-file src="src/ubuntu/toolbar-left.png" />
<resource-file src="src/ubuntu/toolbar-middle.png" />
<resource-file src="src/ubuntu/toolbar-right.png" />
</platform>
<!-- ios -->
<platform name="ios">
<config-file target="config.xml" parent="/*">
@@ -122,9 +180,7 @@
<!-- windows8 -->
<platform name="windows8">
<dependency id="org.apache.cordova.core.file"
url="https://git-wip-us.apache.org/repos/asf/cordova-plugin-file"
commit="master" subdir="/" />
<dependency id="org.apache.cordova.file" />
<config-file target="package.appxmanifest" parent="/Package/Capabilities">
<Capability Name="picturesLibrary" />
<DeviceCapability Name="webcam" />
@@ -137,5 +193,20 @@
</js-module>
</platform>
<!-- firefoxos -->
<platform name="firefoxos">
<config-file target="config.xml" parent="/*">
<feature name="Camera">
<param name="firefoxos-package" value="Camera" />
</feature>
</config-file>
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
<clobbers target="CameraPopoverHandle" />
</js-module>
<js-module src="src/firefoxos/CameraProxy.js" name="CameraProxy">
<runs />
</js-module>
</platform>
</plugin>

View File

@@ -26,9 +26,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.cordova.ExifHelper;
import org.apache.cordova.DirectoryManager;
import org.apache.cordova.FileHelper;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.LOG;
@@ -95,23 +92,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private MediaScannerConnection conn; // Used to update gallery app with newly-written files
private Uri scanMe; // Uri of image to be added to content store
//This should never be null!
//private CordovaInterface cordova;
/**
* Constructor.
*/
public CameraLauncher() {
}
// public void setContext(CordovaInterface mCtx) {
// super.setContext(mCtx);
// if (CordovaInterface.class.isInstance(mCtx))
// cordova = (CordovaInterface) mCtx;
// else
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
// }
/**
* Executes the request and returns PluginResult.
*
@@ -182,6 +162,24 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// LOCAL METHODS
//--------------------------------------------------------------------------
private String getTempDirectoryPath() {
File cache = null;
// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + cordova.getActivity().getPackageName() + "/cache/");
}
// Use internal storage
else {
cache = cordova.getActivity().getCacheDir();
}
// Create the cache directory if it doesn't exist
cache.mkdirs();
return cache.getAbsolutePath();
}
/**
* Take a picture with the camera.
* When an image is captured or the camera view is cancelled, the result is returned
@@ -224,9 +222,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
private File createCaptureFile(int encodingType) {
File photo = null;
if (encodingType == JPEG) {
photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.jpg");
photo = new File(getTempDirectoryPath(), ".Pic.jpg");
} else if (encodingType == PNG) {
photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.png");
photo = new File(getTempDirectoryPath(), ".Pic.png");
} else {
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
}
@@ -290,7 +288,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
ExifHelper exif = new ExifHelper();
try {
if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/.Pic.jpg");
exif.createInFile(getTempDirectoryPath() + "/.Pic.jpg");
exif.readExifData();
rotate = exif.getOrientation();
}
@@ -331,7 +329,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
//Just because we have a media URI doesn't mean we have a real file, we need to make it
uri = Uri.fromFile(new File(FileHelper.getRealPath(inputUri, this.cordova)));
} else {
uri = Uri.fromFile(new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), System.currentTimeMillis() + ".jpg"));
uri = Uri.fromFile(new File(getTempDirectoryPath(), System.currentTimeMillis() + ".jpg"));
}
if (uri == null) {
@@ -451,7 +449,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
if (this.targetHeight > 0 && this.targetWidth > 0) {
try {
// Create an ExifHelper to save the exif data that is lost during compression
String resizePath = DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/resize.jpg";
String resizePath = getTempDirectoryPath() + "/resize.jpg";
// Some content: URIs do not map to file paths (e.g. picasa).
String realPath = FileHelper.getRealPath(uri, this.cordova);
ExifHelper exif = new ExifHelper();
@@ -749,6 +747,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
Uri uri = Uri.parse(contentStore + "/" + id);
this.cordova.getActivity().getContentResolver().delete(uri, null, null);
cursor.close();
}
}

185
src/android/ExifHelper.java Normal file
View File

@@ -0,0 +1,185 @@
/*
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 java.io.IOException;
import android.media.ExifInterface;
public class ExifHelper {
private String aperture = null;
private String datetime = null;
private String exposureTime = null;
private String flash = null;
private String focalLength = null;
private String gpsAltitude = null;
private String gpsAltitudeRef = null;
private String gpsDateStamp = null;
private String gpsLatitude = null;
private String gpsLatitudeRef = null;
private String gpsLongitude = null;
private String gpsLongitudeRef = null;
private String gpsProcessingMethod = null;
private String gpsTimestamp = null;
private String iso = null;
private String make = null;
private String model = null;
private String orientation = null;
private String whiteBalance = null;
private ExifInterface inFile = null;
private ExifInterface outFile = null;
/**
* The file before it is compressed
*
* @param filePath
* @throws IOException
*/
public void createInFile(String filePath) throws IOException {
this.inFile = new ExifInterface(filePath);
}
/**
* The file after it has been compressed
*
* @param filePath
* @throws IOException
*/
public void createOutFile(String filePath) throws IOException {
this.outFile = new ExifInterface(filePath);
}
/**
* Reads all the EXIF data from the input file.
*/
public void readExifData() {
this.aperture = inFile.getAttribute(ExifInterface.TAG_APERTURE);
this.datetime = inFile.getAttribute(ExifInterface.TAG_DATETIME);
this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH);
this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF);
this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
this.iso = inFile.getAttribute(ExifInterface.TAG_ISO);
this.make = inFile.getAttribute(ExifInterface.TAG_MAKE);
this.model = inFile.getAttribute(ExifInterface.TAG_MODEL);
this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION);
this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
}
/**
* Writes the previously stored EXIF data to the output file.
*
* @throws IOException
*/
public void writeExifData() throws IOException {
// Don't try to write to a null file
if (this.outFile == null) {
return;
}
if (this.aperture != null) {
this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperture);
}
if (this.datetime != null) {
this.outFile.setAttribute(ExifInterface.TAG_DATETIME, this.datetime);
}
if (this.exposureTime != null) {
this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime);
}
if (this.flash != null) {
this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash);
}
if (this.focalLength != null) {
this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength);
}
if (this.gpsAltitude != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude);
}
if (this.gpsAltitudeRef != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef);
}
if (this.gpsDateStamp != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp);
}
if (this.gpsLatitude != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude);
}
if (this.gpsLatitudeRef != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef);
}
if (this.gpsLongitude != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude);
}
if (this.gpsLongitudeRef != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef);
}
if (this.gpsProcessingMethod != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod);
}
if (this.gpsTimestamp != null) {
this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp);
}
if (this.iso != null) {
this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso);
}
if (this.make != null) {
this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make);
}
if (this.model != null) {
this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model);
}
if (this.orientation != null) {
this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation);
}
if (this.whiteBalance != null) {
this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance);
}
this.outFile.saveAttributes();
}
public int getOrientation() {
int o = Integer.parseInt(this.orientation);
if (o == ExifInterface.ORIENTATION_NORMAL) {
return 0;
} else if (o == ExifInterface.ORIENTATION_ROTATE_90) {
return 90;
} else if (o == ExifInterface.ORIENTATION_ROTATE_180) {
return 180;
} else if (o == ExifInterface.ORIENTATION_ROTATE_270) {
return 270;
} else {
return 0;
}
}
public void resetOrientation() {
this.orientation = "" + ExifInterface.ORIENTATION_NORMAL;
}
}

158
src/android/FileHelper.java Normal file
View File

@@ -0,0 +1,158 @@
/*
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.database.Cursor;
import android.net.Uri;
import android.webkit.MimeTypeMap;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.LOG;
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(String uriString, CordovaInterface cordova) {
String realPath = null;
if (uriString.startsWith("content://")) {
String[] proj = { _DATA };
Cursor cursor = cordova.getActivity().managedQuery(Uri.parse(uriString), proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA);
cursor.moveToFirst();
realPath = cursor.getString(column_index);
if (realPath == null) {
LOG.e(LOG_TAG, "Could get real path for URI string %s", uriString);
}
} else if (uriString.startsWith("file://")) {
realPath = uriString.substring(7);
if (realPath.startsWith("/android_asset/")) {
LOG.e(LOG_TAG, "Cannot get real path for URI string %s because it is a file:///android_asset/ URI.", uriString);
realPath = null;
}
} else {
realPath = uriString;
}
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(Uri uri, CordovaInterface cordova) {
return FileHelper.getRealPath(uri.toString(), cordova);
}
/**
* 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 {
if (uriString.startsWith("content")) {
Uri uri = Uri.parse(uriString);
return 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);
return cordova.getActivity().getAssets().open(relativePath);
} else {
return new FileInputStream(getRealPath(uriString, cordova));
}
} else {
return new FileInputStream(getRealPath(uriString, cordova));
}
}
/**
* 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;
}
}

View File

@@ -0,0 +1,51 @@
/*
*
* 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.
*
*/
function takePicture(success, error, opts) {
var pick = new MozActivity({
name: "pick",
data: {
type: ["image/*"]
}
});
pick.onerror = error || function() {};
pick.onsuccess = function() {
// image is returned as Blob in this.result.blob
// we need to call success with url or base64 encoded image
if (opts && opts.destinationType == 0) {
// TODO: base64
return;
}
if (!opts || !opts.destinationType || opts.destinationType > 0) {
// url
return success(window.URL.createObjectURL(this.result.blob));
}
};
}
module.exports = {
takePicture: takePicture,
cleanup: function(){}
};
require("cordova/firefoxos/commandProxy").add("Camera", module.exports);

32
src/firefoxos/camera.js Normal file
View File

@@ -0,0 +1,32 @@
var firefoxos = require('cordova/platform');
function getPicture(cameraSuccess, cameraError, cameraOptions) {
cameraError = cameraError || function(){};
var pick = new MozActivity({
name: "pick",
data: {
type: ["image/png", "image/jpg", "image/jpeg"]
}
});
pick.onerror = cameraError;
pick.onsuccess = function() {
// image is returned as Blob in this.result.blob
// we need to call cameraSuccess with url or base64 encoded image
if (cameraOptions && cameraOptions.destinationType == 0) {
// TODO: base64
return;
}
if (!cameraOptions || !cameraOptions.destinationTyoe || cameraOptions.destinationType > 0) {
// url
return cameraSuccess(window.URL.createObjectURL(this.result.blob));
}
};
}
var Camera = {
takePicture: getPicture,
cleanup: function(){}
};
firefoxos.registerPlugin('Camera', Camera);

View File

@@ -150,9 +150,11 @@ static NSSet* org_apache_cordova_validArrowDirections;
NSDictionary* options = [command.arguments objectAtIndex:10 withDefault:nil];
[self displayPopover:options];
} else {
if ([self.viewController respondsToSelector:@selector(presentViewController:::)]) {
SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
if ([self.viewController respondsToSelector:selector]) {
[self.viewController presentViewController:cameraPicker animated:YES completion:nil];
} else {
// deprecated as of iOS >= 6.0
[self.viewController presentModalViewController:cameraPicker animated:YES];
}
}
@@ -734,4 +736,21 @@ static NSSet* org_apache_cordova_validArrowDirections;
@synthesize webView;
@synthesize popoverSupported;
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (UIViewController*)childViewControllerForStatusBarHidden {
return nil;
}
- (void)viewWillAppear:(BOOL)animated {
SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
if ([self respondsToSelector:sel]) {
[self performSelector:sel withObject:nil afterDelay:0];
}
[super viewWillAppear:animated];
}
@end

View File

@@ -0,0 +1,119 @@
/*
*
* Copyright 2013 Canonical Ltd.
*
* 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.
*
*/
import QtQuick 2.0
import QtMultimedia 5.0
Rectangle {
property string shootImagePath: "shoot.png"
function isSuffix(str, suffix) {
return String(str).substr(String(str).length - suffix.length) == suffix
}
id: ui
color: "#252423"
anchors.fill: parent
Camera {
objectName: "camera"
id: camera
onError: {
console.log(errorString);
}
videoRecorder.audioBitRate: 128000
videoRecorder.mediaContainer: "mp4"
imageCapture {
onImageSaved: {
root.exec("Camera", "onImageSaved", [path]);
ui.destroy();
}
}
}
VideoOutput {
id: output
source: camera
width: parent.width
height: parent.height
}
Item {
anchors.bottom: parent.bottom
width: parent.width
height: shootButton.height
BorderImage {
id: leftBackground
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: middle.left
anchors.topMargin: units.dp(2)
anchors.bottomMargin: units.dp(2)
source: "toolbar-left.png"
Image {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: parent.iconSpacing
source: "back.png"
width: units.gu(6)
height: units.gu(5)
MouseArea {
anchors.fill: parent
onClicked: {
root.exec("Camera", "cancel");
}
}
}
}
BorderImage {
id: middle
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
height: shootButton.height + units.gu(1)
width: shootButton.width
source: "toolbar-middle.png"
Image {
id: shootButton
width: units.gu(8)
height: width
anchors.horizontalCenter: parent.horizontalCenter
source: shootImagePath
MouseArea {
anchors.fill: parent
onClicked: {
camera.imageCapture.capture();
}
}
}
}
BorderImage {
id: rightBackground
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: middle.right
anchors.topMargin: units.dp(2)
anchors.bottomMargin: units.dp(2)
source: "toolbar-right.png"
}
}
}

BIN
src/ubuntu/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

143
src/ubuntu/camera.cpp Normal file
View File

@@ -0,0 +1,143 @@
/*
*
* 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.
*
*/
#include "camera.h"
#include <cordova.h>
#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <QGraphicsObject>
#include <QCloseEvent>
#include <QQuickItem>
const char code[] = "\
var component, object; \
function createObject() { \
component = Qt.createComponent(%1); \
if (component.status == Component.Ready) \
finishCreation(); \
else \
component.statusChanged.connect(finishCreation); \
} \
function finishCreation() { \
CordovaWrapper.object = component.createObject(root, \
{root: root, cordova: cordova}); \
} \
createObject()";
Camera::Camera(Cordova *cordova):
CPlugin(cordova),
_lastScId(0),
_lastEcId(0) {
}
bool Camera::preprocessImage(QString &path) {
bool convertToPNG = (*_options.find("encodingType")).toInt() == Camera::PNG;
int quality = (*_options.find("quality")).toInt();
int width = (*_options.find("targetWidth")).toInt();
int height = (*_options.find("targetHeight")).toInt();
QImage image(path);
if (width <= 0)
width = image.width();
if (height <= 0)
height = image.height();
image = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
QFile oldImage(path);
QTemporaryFile newImage;
const char *type;
if (convertToPNG) {
newImage.setFileTemplate("imgXXXXXX.png");
type = "png";
} else {
newImage.setFileTemplate("imgXXXXXX.jpg");
type = "jpg";
}
newImage.open();
newImage.setAutoRemove(false);
image.save(newImage.fileName(), type, quality);
path = newImage.fileName();
oldImage.remove();
return true;
}
void Camera::onImageSaved(QString path) {
bool dataURL = _options.find("destinationType")->toInt() == Camera::DATA_URL;
QString cbParams;
if (preprocessImage(path)) {
QString absolutePath = QFileInfo(path).absoluteFilePath();
if (dataURL) {
QFile image(absolutePath);
image.open(QIODevice::ReadOnly);
QByteArray content = image.readAll().toBase64();
cbParams = QString("\"%1\"").arg(content.data());
image.remove();
} else {
cbParams = CordovaInternal::format(QUrl::fromLocalFile(absolutePath).toString());
}
}
this->callback(_lastScId, cbParams);
_lastEcId = _lastScId = 0;
}
void Camera::takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &/*popoverOptions*/, int/*cameraDirection*/) {
if (_camera.isNull()) {
_camera = QSharedPointer<QCamera>(new QCamera());
}
if (((_lastScId || _lastEcId) && (_lastScId != scId && _lastEcId != ecId)) || !_camera->isAvailable() || _camera->lockStatus() != QCamera::Unlocked) {
this->cb(_lastEcId, "Device is busy");
return;
}
_options.clear();
_options.insert("quality", quality);
_options.insert("destinationType", destinationType);
_options.insert("targetWidth", targetWidth);
_options.insert("targetHeight", targetHeight);
_options.insert("encodingType", encodingType);
_lastScId = scId;
_lastEcId = ecId;
QString path = m_cordova->get_app_dir() + "/../qml/CaptureWidget.qml";
// TODO: relative url
QString qml = QString(code).arg(CordovaInternal::format(path));
m_cordova->execQML(qml);
}
void Camera::cancel() {
m_cordova->execQML("CordovaWrapper.object.destroy()");
this->cb(_lastEcId, "canceled");
_lastEcId = _lastScId = 0;
}

76
src/ubuntu/camera.h Normal file
View File

@@ -0,0 +1,76 @@
/*
*
* 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.
*
*/
#ifndef CAMERA_H
#define CAMERA_H
#include <cplugin.h>
#include <QtCore>
#include <QQuickView>
#include <QCamera>
#include <QtMultimediaWidgets/QCameraViewfinder>
#include <QCameraImageCapture>
class Camera: public CPlugin {
Q_OBJECT
public:
explicit Camera(Cordova *cordova);
virtual const QString fullName() override {
return Camera::fullID();
}
virtual const QString shortName() override {
return "Camera";
}
static const QString fullID() {
return "Camera";
}
public slots:
void takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &popoverOptions, int cameraDirection);
void cancel();
void onImageSaved(QString path);
private:
bool preprocessImage(QString &path);
int _lastScId;
int _lastEcId;
QSharedPointer<QCamera> _camera;
QVariantMap _options;
protected:
enum DestinationType {
DATA_URL = 0,
FILE_URI = 1
};
enum EncodingType {
JPEG = 0,
PNG = 1
};
};
#endif // CAMERA_H

BIN
src/ubuntu/shoot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
src/ubuntu/toolbar-left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -24,9 +24,9 @@
var cordova = require('cordova'),
Camera = require('./Camera'),
FileEntry = require('org.apache.cordova.core.file.FileEntry'),
FileError = require('org.apache.cordova.core.file.FileError'),
FileReader = require('org.apache.cordova.core.file.FileReader');
FileEntry = require('org.apache.cordova.file.FileEntry'),
FileError = require('org.apache.cordova.file.FileError'),
FileReader = require('org.apache.cordova.file.FileReader');
module.exports = {
@@ -338,4 +338,4 @@ module.exports = {
}
};
require("cordova/commandProxy").add("Camera",module.exports);
require("cordova/windows8/commandProxy").add("Camera",module.exports);

View File

@@ -340,7 +340,7 @@
document.addEventListener("deviceready", function() {
deviceReady = true;
platformId = cordova.require('cordova/platform').id;
CameraPopoverOptions = cordova.require('org.apache.cordova.core.camera.CameraPopoverOptions');
CameraPopoverOptions = cordova.require('org.apache.cordova.camera.CameraPopoverOptions');
console.log("Device="+device.platform+" "+device.version);
createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault);
createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault);

View File

@@ -20,7 +20,9 @@
*/
var PLAT;
if (/Android/.exec(navigator.userAgent)) {
if (/cordova-amazon-fireos/.exec(navigator.userAgent)) {
PLAT = 'amazon-fireos';
}else if (/Android/.exec(navigator.userAgent)) {
PLAT = 'android';
} else if (/(iPad)|(iPhone)|(iPod)/.exec(navigator.userAgent)) {
PLAT = 'ios';
@@ -61,7 +63,7 @@ if (!window._doNotWriteCordovaScript) {
}
function backHome() {
if (window.device && device.platform && device.platform.toLowerCase() == 'android') {
if (window.device && device.platform && (device.platform.toLowerCase() == 'android' || device.platform.toLowerCase() == 'amazon-fireos')) {
navigator.app.backHistory();
}
else {

View File

@@ -21,8 +21,9 @@
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
Camera = require('./Camera'),
CameraPopoverHandle = require('./CameraPopoverHandle');
Camera = require('./Camera');
// XXX: commented out
//CameraPopoverHandle = require('./CameraPopoverHandle');
var cameraExport = {};
@@ -63,7 +64,8 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) {
mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
exec(successCallback, errorCallback, "Camera", "takePicture", args);
return new CameraPopoverHandle();
// XXX: commented out
//return new CameraPopoverHandle();
};
cameraExport.cleanup = function(successCallback, errorCallback) {