Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating to the New Architecture #126

Merged
merged 5 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 63 additions & 28 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@

buildscript {
repositories {
google()
mavenCentral()
}
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
dependencies {
classpath "com.android.tools.build:gradle:7.2.1"
}
}

def isNewArchitectureEnabled() {
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
}

apply plugin: "com.android.library"

if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}

def getExtOrDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['RNImageEditor_' + name]
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["RNImageEditor_" + name]
}

def getExtOrIntegerDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['RNImageEditor_' + name]).toInteger()
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["RNImageEditor_" + name]).toInteger()
}

def supportsNamespace() {
Expand All @@ -27,34 +36,60 @@ def supportsNamespace() {
return (major == 7 && minor >= 3) || major >= 8
}


apply plugin: 'com.android.library'

android {
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
buildToolsVersion getExtOrDefault('buildToolsVersion')
if (supportsNamespace()) {
namespace "com.reactnativecommunity.imageeditor"

if (supportsNamespace()) {
namespace "com.reactnativecommunity.imageeditor"
sourceSets {
main {
manifest.srcFile "src/main/AndroidManifestNew.xml"
}
}
}
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
defaultConfig {
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
}
buildFeatures {
buildConfig true
}

sourceSets {
main {
manifest.srcFile "src/main/AndroidManifestNew.xml"
}
}
buildTypes {
release {
minifyEnabled false
}
}

defaultConfig {
minSdkVersion getExtOrIntegerDefault('minSdkVersion')
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
lintOptions {
disable "GradleCompatible"
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

sourceSets {
main {
if (isNewArchitectureEnabled()) {
java.srcDirs += ["src/newarch", "${project.buildDir}/generated/source/codegen/java"]
} else {
java.srcDirs += ["src/oldarch"]
}
}
}
}

repositories {
mavenCentral()
mavenCentral()
google()
}

dependencies {
api 'com.facebook.react:react-native:+'
// For < 0.71, this will be from the local maven repo
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
}

7 changes: 3 additions & 4 deletions android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
RNImageEditor_compileSdkVersion=28
RNImageEditor_buildToolsVersion=28.0.3
RNImageEditor_targetSdkVersion=28
RNImageEditor_minSdkVersion=19
RNImageEditor_compileSdkVersion=34
RNImageEditor_targetSdkVersion=34
RNImageEditor_minSdkVersion=21
3 changes: 2 additions & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Sat Nov 04 23:34:44 CET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
3 changes: 0 additions & 3 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.reactnativecommunity.imageeditor">

</manifest>

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.reactnativecommunity.imageeditor;

import javax.annotation.Nullable;
Expand All @@ -18,9 +17,7 @@
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import android.content.ContentResolver;
Expand All @@ -43,23 +40,20 @@
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.common.ReactConstants;

/**
* Native module that provides image cropping functionality.
*/
public class ImageEditorModule extends ReactContextBaseJavaModule {
public class ImageEditorModuleImpl {
private ReactApplicationContext reactContext;

protected static final String NAME = "RNCImageEditor";

private static final List<String> LOCAL_URI_PREFIXES = Arrays.asList(
ContentResolver.SCHEME_FILE,
ContentResolver.SCHEME_CONTENT,
ContentResolver.SCHEME_ANDROID_RESOURCE
ContentResolver.SCHEME_FILE,
ContentResolver.SCHEME_CONTENT,
ContentResolver.SCHEME_ANDROID_RESOURCE
);

private static final String TEMP_FILE_PREFIX = "ReactNative_cropped_image_";
Expand Down Expand Up @@ -95,24 +89,13 @@ public class ImageEditorModule extends ReactContextBaseJavaModule {
ExifInterface.TAG_WHITE_BALANCE
};

public ImageEditorModule(ReactApplicationContext reactContext) {
super(reactContext);
new CleanTask(getReactApplicationContext()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

@Override
public String getName() {
return NAME;
}

@Override
public Map<String, Object> getConstants() {
return Collections.emptyMap();
public ImageEditorModuleImpl(ReactApplicationContext context) {
reactContext = context;
new CleanTask(reactContext).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

@Override
public void onCatalystInstanceDestroy() {
new CleanTask(getReactApplicationContext()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new CleanTask(reactContext).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

/**
Expand All @@ -139,12 +122,12 @@ protected void doInBackgroundGuarded(Void... params) {

private void cleanDirectory(File directory) {
File[] toDelete = directory.listFiles(
new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
return filename.startsWith(TEMP_FILE_PREFIX);
}
});
new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
return filename.startsWith(TEMP_FILE_PREFIX);
}
});
if (toDelete != null) {
for (File file: toDelete) {
file.delete();
Expand All @@ -166,30 +149,29 @@ public boolean accept(File dir, String filename) {
* @param promise Promise to be resolved when the image has been cropped; the only argument that
* is passed to this is the file:// URI of the new image
*/
@ReactMethod
public void cropImage(
String uri,
ReadableMap options,
Promise promise) {
String uri,
ReadableMap options,
Promise promise) {
ReadableMap offset = options.hasKey("offset") ? options.getMap("offset") : null;
ReadableMap size = options.hasKey("size") ? options.getMap("size") : null;
if (offset == null || size == null ||
!offset.hasKey("x") || !offset.hasKey("y") ||
!size.hasKey("width") || !size.hasKey("height")) {
!offset.hasKey("x") || !offset.hasKey("y") ||
!size.hasKey("width") || !size.hasKey("height")) {
throw new JSApplicationIllegalArgumentException("Please specify offset and size");
}
if (uri == null || uri.isEmpty()) {
throw new JSApplicationIllegalArgumentException("Please specify a URI");
}

CropTask cropTask = new CropTask(
getReactApplicationContext(),
uri,
(int) offset.getDouble("x"),
(int) offset.getDouble("y"),
(int) size.getDouble("width"),
(int) size.getDouble("height"),
promise);
reactContext,
uri,
(int) offset.getDouble("x"),
(int) offset.getDouble("y"),
(int) size.getDouble("width"),
(int) size.getDouble("height"),
promise);
if (options.hasKey("displaySize")) {
ReadableMap targetSize = options.getMap("displaySize");
cropTask.setTargetSize(
Expand All @@ -211,17 +193,17 @@ private static class CropTask extends GuardedAsyncTask<Void, Void> {
final Promise mPromise;

private CropTask(
ReactContext context,
String uri,
int x,
int y,
int width,
int height,
Promise promise) {
ReactContext context,
String uri,
int x,
int y,
int width,
int height,
Promise promise) {
super(context);
if (x < 0 || y < 0 || width <= 0 || height <= 0) {
throw new JSApplicationIllegalArgumentException(String.format(
"Invalid crop rectangle: [%d, %d, %d, %d]", x, y, width, height));
"Invalid crop rectangle: [%d, %d, %d, %d]", x, y, width, height));
}
mContext = context;
mUri = uri;
Expand All @@ -235,7 +217,7 @@ private CropTask(
public void setTargetSize(int width, int height) {
if (width <= 0 || height <= 0) {
throw new JSApplicationIllegalArgumentException(String.format(
"Invalid target size: [%d, %d]", width, height));
"Invalid target size: [%d, %d]", width, height));
}
mTargetWidth = width;
mTargetHeight = height;
Expand Down Expand Up @@ -314,10 +296,10 @@ private Bitmap crop(BitmapFactory.Options outOptions) throws IOException {
* @param outOptions Bitmap options, useful to determine {@code outMimeType}.
*/
private Bitmap cropAndResize(
int targetWidth,
int targetHeight,
BitmapFactory.Options outOptions)
throws IOException {
int targetWidth,
int targetHeight,
BitmapFactory.Options outOptions)
throws IOException {
Assertions.assertNotNull(outOptions);

// Loading large bitmaps efficiently:
Expand Down Expand Up @@ -450,7 +432,7 @@ private static Bitmap.CompressFormat getCompressFormatForType(String type) {
}

private static void writeCompressedBitmapToFile(Bitmap cropped, String mimeType, File tempFile)
throws IOException {
throws IOException {
OutputStream out = new FileOutputStream(tempFile);
try {
cropped.compress(getCompressFormatForType(mimeType), COMPRESS_QUALITY, out);
Expand All @@ -468,7 +450,7 @@ private static void writeCompressedBitmapToFile(Bitmap cropped, String mimeType,
* @param mimeType the MIME type of the file to create (image/*)
*/
private static File createTempFile(Context context, @Nullable String mimeType)
throws IOException {
throws IOException {
File externalCacheDir = context.getExternalCacheDir();
File internalCacheDir = context.getCacheDir();
File cacheDir;
Expand All @@ -482,7 +464,7 @@ else if (internalCacheDir == null) {
cacheDir = externalCacheDir;
} else {
cacheDir = externalCacheDir.getFreeSpace() > internalCacheDir.getFreeSpace() ?
externalCacheDir : internalCacheDir;
externalCacheDir : internalCacheDir;
}
return File.createTempFile(TEMP_FILE_PREFIX, getFileExtensionForType(mimeType), cacheDir);
}
Expand All @@ -499,7 +481,7 @@ private static int getDecodeSampleSize(int width, int height, int targetWidth, i
int halfHeight = height / 2;
int halfWidth = width / 2;
while ((halfWidth / inSampleSize) >= targetWidth
&& (halfHeight / inSampleSize) >= targetHeight) {
&& (halfHeight / inSampleSize) >= targetHeight) {
inSampleSize *= 2;
}
}
Expand Down
Loading