Create local cache directory and save image there when photo is taken.

This commit is contained in:
Joao Fidelis 2018-01-23 01:19:17 -02:00
parent b6710741b9
commit f53aab5729
7 changed files with 132 additions and 17 deletions

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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.");
// } }
} }
/** /**

View 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);

View File

@ -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);
}
}

View 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;
}
}