mirror of
https://github.com/status-im/react-native-camera.git
synced 2025-02-24 17:58:20 +00:00
Create local cache directory and save image there when photo is taken.
This commit is contained in:
parent
b6710741b9
commit
f53aab5729
@ -65,6 +65,8 @@ public class MutableImage {
|
|||||||
return currentRepresentation.getHeight();
|
return currentRepresentation.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Bitmap getBitmap() { return currentRepresentation; }
|
||||||
|
|
||||||
public void fixOrientation() throws ImageMutationFailedException {
|
public void fixOrientation() throws ImageMutationFailedException {
|
||||||
try {
|
try {
|
||||||
Metadata metadata = originalImageMetaData();
|
Metadata metadata = originalImageMetaData();
|
||||||
|
@ -2,6 +2,7 @@ package org.reactnative.camera;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.reactnative.camera.utils.ScopedContext;
|
||||||
import org.reactnative.facedetector.RNFaceDetector;
|
import org.reactnative.facedetector.RNFaceDetector;
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
@ -25,7 +26,7 @@ public class CameraModule extends ReactContextBaseJavaModule {
|
|||||||
|
|
||||||
private static ReactApplicationContext mReactContext;
|
private static ReactApplicationContext mReactContext;
|
||||||
|
|
||||||
// private static ScopedContext mScopedContext;
|
private static ScopedContext mScopedContext;
|
||||||
static final int VIDEO_2160P = 0;
|
static final int VIDEO_2160P = 0;
|
||||||
static final int VIDEO_1080P = 1;
|
static final int VIDEO_1080P = 1;
|
||||||
static final int VIDEO_720P = 2;
|
static final int VIDEO_720P = 2;
|
||||||
@ -58,14 +59,15 @@ public class CameraModule extends ReactContextBaseJavaModule {
|
|||||||
public CameraModule(ReactApplicationContext reactContext) {
|
public CameraModule(ReactApplicationContext reactContext) {
|
||||||
super(reactContext);
|
super(reactContext);
|
||||||
mReactContext = reactContext;
|
mReactContext = reactContext;
|
||||||
|
mScopedContext = new ScopedContext(mReactContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReactApplicationContext getReactContextSingleton() {
|
public static ReactApplicationContext getReactContextSingleton() {
|
||||||
return mReactContext;
|
return mReactContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Context getScopedContextSingleton() {
|
public static ScopedContext getScopedContext() {
|
||||||
return mReactContext;
|
return mScopedContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,6 +6,8 @@ import android.os.Build;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.reactnative.camera.tasks.ResolveTakenPictureAsyncTask;
|
import org.reactnative.camera.tasks.ResolveTakenPictureAsyncTask;
|
||||||
|
import org.reactnative.camera.utils.ScopedContext;
|
||||||
|
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
|
@ -16,6 +16,8 @@ import org.reactnative.camera.tasks.FaceDetectorAsyncTask;
|
|||||||
import org.reactnative.camera.tasks.FaceDetectorAsyncTaskDelegate;
|
import org.reactnative.camera.tasks.FaceDetectorAsyncTaskDelegate;
|
||||||
import org.reactnative.camera.tasks.ResolveTakenPictureAsyncTask;
|
import org.reactnative.camera.tasks.ResolveTakenPictureAsyncTask;
|
||||||
import org.reactnative.camera.utils.ImageDimensions;
|
import org.reactnative.camera.utils.ImageDimensions;
|
||||||
|
import org.reactnative.camera.utils.RNFileUtils;
|
||||||
|
import org.reactnative.camera.utils.ScopedContext;
|
||||||
import org.reactnative.facedetector.RNFaceDetector;
|
import org.reactnative.facedetector.RNFaceDetector;
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.LifecycleEventListener;
|
import com.facebook.react.bridge.LifecycleEventListener;
|
||||||
@ -81,7 +83,8 @@ public class RNCameraView extends CameraView implements LifecycleEventListener,
|
|||||||
public void onPictureTaken(CameraView cameraView, final byte[] data) {
|
public void onPictureTaken(CameraView cameraView, final byte[] data) {
|
||||||
Promise promise = mPictureTakenPromises.poll();
|
Promise promise = mPictureTakenPromises.poll();
|
||||||
ReadableMap options = mPictureTakenOptions.remove(promise);
|
ReadableMap options = mPictureTakenOptions.remove(promise);
|
||||||
new ResolveTakenPictureAsyncTask(data, promise, options).execute();
|
File cacheDirectory = CameraModule.getScopedContext().getCacheDirectory();
|
||||||
|
new ResolveTakenPictureAsyncTask(data, promise, options, cacheDirectory).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,8 +92,7 @@ public class RNCameraView extends CameraView implements LifecycleEventListener,
|
|||||||
if (mVideoRecordedPromise != null) {
|
if (mVideoRecordedPromise != null) {
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
WritableMap result = Arguments.createMap();
|
WritableMap result = Arguments.createMap();
|
||||||
// TODO - fix this
|
result.putString("uri", RNFileUtils.uriFromFile(new File(path)).toString());
|
||||||
//result.putString("uri", ExpFileUtils.uriFromFile(new File(path)).toString());
|
|
||||||
mVideoRecordedPromise.resolve(result);
|
mVideoRecordedPromise.resolve(result);
|
||||||
} else {
|
} else {
|
||||||
mVideoRecordedPromise.reject("E_RECORDING", "Couldn't stop recording - there is none in progress");
|
mVideoRecordedPromise.reject("E_RECORDING", "Couldn't stop recording - there is none in progress");
|
||||||
@ -156,10 +158,9 @@ public class RNCameraView extends CameraView implements LifecycleEventListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void record(ReadableMap options, final Promise promise) {
|
public void record(ReadableMap options, final Promise promise) {
|
||||||
// try {
|
try {
|
||||||
// TODO - fix this
|
File cacheDirectory = CameraModule.getScopedContext().getCacheDirectory();
|
||||||
String path = "";
|
String path = RNFileUtils.getOutputFilePath(cacheDirectory, ".mp4");
|
||||||
//String path = ExpFileUtils.generateOutputPath(CameraModule.getScopedContextSingleton().getCacheDir(), "Camera", ".mp4");
|
|
||||||
int maxDuration = options.hasKey("maxDuration") ? options.getInt("maxDuration") : -1;
|
int maxDuration = options.hasKey("maxDuration") ? options.getInt("maxDuration") : -1;
|
||||||
int maxFileSize = options.hasKey("maxFileSize") ? options.getInt("maxFileSize") : -1;
|
int maxFileSize = options.hasKey("maxFileSize") ? options.getInt("maxFileSize") : -1;
|
||||||
|
|
||||||
@ -175,9 +176,9 @@ public class RNCameraView extends CameraView implements LifecycleEventListener,
|
|||||||
} else {
|
} else {
|
||||||
promise.reject("E_RECORDING_FAILED", "Starting video recording failed. Another recording might be in progress.");
|
promise.reject("E_RECORDING_FAILED", "Starting video recording failed. Another recording might be in progress.");
|
||||||
}
|
}
|
||||||
// } catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// promise.reject("E_RECORDING_FAILED", "Starting video recording failed - could not create video file.");
|
promise.reject("E_RECORDING_FAILED", "Starting video recording failed - could not create video file.");
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package org.reactnative.camera.tasks;
|
package org.reactnative.camera.tasks;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Bitmap;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.media.ExifInterface;
|
import android.support.media.ExifInterface;
|
||||||
|
|
||||||
import org.reactnative.MutableImage;
|
import org.reactnative.MutableImage;
|
||||||
import org.reactnative.camera.RNCameraViewHelper;
|
import org.reactnative.camera.RNCameraViewHelper;
|
||||||
|
import org.reactnative.camera.utils.RNFileUtils;
|
||||||
|
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
@ -14,6 +16,9 @@ import com.facebook.react.bridge.ReadableMap;
|
|||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, WritableMap> {
|
public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, WritableMap> {
|
||||||
@ -21,6 +26,7 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
|
|||||||
private Promise mPromise;
|
private Promise mPromise;
|
||||||
private byte[] mImageData;
|
private byte[] mImageData;
|
||||||
private ReadableMap mOptions;
|
private ReadableMap mOptions;
|
||||||
|
private File mCacheDirectory;
|
||||||
|
|
||||||
public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, ReadableMap options) {
|
public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, ReadableMap options) {
|
||||||
mPromise = promise;
|
mPromise = promise;
|
||||||
@ -28,6 +34,13 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
|
|||||||
mImageData = imageData;
|
mImageData = imageData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResolveTakenPictureAsyncTask(byte[] imageData, Promise promise, ReadableMap options, File cacheDirectory) {
|
||||||
|
mPromise = promise;
|
||||||
|
mOptions = options;
|
||||||
|
mImageData = imageData;
|
||||||
|
mCacheDirectory = cacheDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
private int getQuality() {
|
private int getQuality() {
|
||||||
return (int) (mOptions.getDouble("quality") * 100);
|
return (int) (mOptions.getDouble("quality") * 100);
|
||||||
}
|
}
|
||||||
@ -52,9 +65,14 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
|
|||||||
response.putMap("exif", exifData);
|
response.putMap("exif", exifData);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: create local cache directory, save image to file and insert into response "uri" key
|
ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
|
||||||
// with the path to the file
|
mutableImage.getBitmap().compress(Bitmap.CompressFormat.JPEG, getQuality(), imageStream);
|
||||||
//response.putString("uri", outputPath);
|
|
||||||
|
// Write compressed image to file in cache directory
|
||||||
|
String filePath = writeStreamToFile(imageStream);
|
||||||
|
File imageFile = new File(filePath);
|
||||||
|
String fileUri = Uri.fromFile(imageFile).toString();
|
||||||
|
response.putString("uri", fileUri);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (Resources.NotFoundException e) {
|
} catch (Resources.NotFoundException e) {
|
||||||
@ -78,6 +96,35 @@ public class ResolveTakenPictureAsyncTask extends AsyncTask<Void, Void, Writable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String writeStreamToFile(ByteArrayOutputStream inputStream) throws IOException {
|
||||||
|
String outputPath = null;
|
||||||
|
IOException exception = null;
|
||||||
|
FileOutputStream outputStream = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
outputPath = RNFileUtils.getOutputFilePath(mCacheDirectory, ".jpg");
|
||||||
|
outputStream = new FileOutputStream(outputPath);
|
||||||
|
inputStream.writeTo(outputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
exception = e;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (outputStream != null) {
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exception != null) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputPath;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(WritableMap response) {
|
protected void onPostExecute(WritableMap response) {
|
||||||
super.onPostExecute(response);
|
super.onPostExecute(response);
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.reactnative.camera.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by jgfidelis on 23/01/18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RNFileUtils {
|
||||||
|
|
||||||
|
public static File ensureDirExists(File dir) throws IOException {
|
||||||
|
if (!(dir.isDirectory() || dir.mkdirs())) {
|
||||||
|
throw new IOException("Couldn't create directory '" + dir + "'");
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getOutputFilePath(File directory, String extension) throws IOException {
|
||||||
|
ensureDirExists(directory);
|
||||||
|
String filename = UUID.randomUUID().toString();
|
||||||
|
return directory + File.separator + filename + extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Uri uriFromFile(File file) {
|
||||||
|
return Uri.fromFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.reactnative.camera.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by jgfidelis on 23/01/18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ScopedContext {
|
||||||
|
|
||||||
|
private File cacheDirectory = null;
|
||||||
|
|
||||||
|
public ScopedContext(Context context) {
|
||||||
|
createCacheDirectory(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createCacheDirectory(Context context) {
|
||||||
|
cacheDirectory = new File(context.getCacheDir() + "/Camera/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getCacheDirectory() {
|
||||||
|
return cacheDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user