Minor Android fixes for empty/failed return paths (#67)

- Throw exception instead of returning null sourceImage, which avoids
  returning pseudo-empty "file:" string to Javascript on failure
- Use constant strings for checking path prefixes
- Cleanup of conditional statements for checking path prefixes
- Additional try-catch statements, contributing more-fine-grained
  error messages

Other
- Updated .gitignore to latest React Native template
- Updated Android gradle scripts
- Updated package.json's in root and in example to point to
  correct react/react-native versions, and to use local code
  for this library directly in the example app
This commit is contained in:
Abe Botros 2017-02-10 02:21:55 -08:00 committed by Florian Rival
parent d762433fe8
commit aef2a9c7d8
8 changed files with 92 additions and 149 deletions

52
.gitignore vendored
View File

@ -1,8 +1,9 @@
node_modules
workbench
*.log
# Xcode
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
@ -12,10 +13,45 @@ build/
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.xcworkspace
!default.xcworkspace
xcuserdata
profile
*.xccheckout
*.moved-aside
DerivedData
.idea/
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
# node.js
#
node_modules/
npm-debug.log
# BUCK
buck-out/
\.buckd/
android/app/libs
*.keystore
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
# APK
android/app/*.apk

View File

@ -1,3 +1,14 @@
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
}
}
apply plugin: 'com.android.library'
android {
@ -17,6 +28,10 @@ android {
}
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.facebook.react:react-native:+'
}

View File

@ -29,7 +29,9 @@ import java.util.Date;
*/
class ImageResizer {
private final static String BASE64_PREFIX = "data:image/";
public final static String BASE64_PREFIX = "data:image/";
public final static String CONTENT_PREFIX = "content://";
public final static String FILE_PREFIX = "file:";
/**
* Resize the specified bitmap, keeping its aspect ratio.
@ -188,11 +190,20 @@ class ImageResizer {
/**
* Load a bitmap either from a real file or using the {@link ContentResolver} of the current
* {@link Context} (to read gallery images for example).
*
* Note that, when options.inJustDecodeBounds = true, we actually expect sourceImage to remain
* as null (see https://developer.android.com/training/displaying-bitmaps/load-bitmap.html), so
* getting null sourceImage at the completion of this method is not always worthy of an error.
*/
private static Bitmap loadBitmap(Context context, String imagePath, BitmapFactory.Options options) throws IOException {
Bitmap sourceImage = null;
if (!imagePath.startsWith("content://") && !imagePath.startsWith("file://")) {
sourceImage = BitmapFactory.decodeFile(imagePath, options);
if (!imagePath.startsWith(CONTENT_PREFIX)) {
try {
sourceImage = BitmapFactory.decodeFile(imagePath, options);
} catch (Exception e) {
e.printStackTrace();
throw new IOException("Error decoding image file");
}
} else {
ContentResolver cr = context.getContentResolver();
InputStream input = cr.openInputStream(Uri.parse(imagePath));
@ -256,16 +267,16 @@ class ImageResizer {
int quality, int rotation, String outputPath) throws IOException {
Bitmap sourceImage = null;
// If the BASE64_PREFIX is absent, load bitmap from a file. Otherwise, load from base64.
if (imagePath.indexOf(BASE64_PREFIX) < 0) {
// If the BASE64_PREFIX is absent, load bitmap from a file. Otherwise, load from base64.
if (!imagePath.startsWith(BASE64_PREFIX)) {
sourceImage = ImageResizer.loadBitmapFromFile(context, imagePath, newWidth, newHeight);
}
else {
sourceImage = ImageResizer.loadBitmapFromBase64(imagePath);
}
if (sourceImage == null){
return "";
if (sourceImage == null) {
throw new IOException("Unable to load source image from path");
}
// Scale it first so there are fewer pixels to transform in the rotation

View File

@ -45,13 +45,19 @@ class ImageResizerModule extends ReactContextBaseJavaModule {
String compressFormatString, int quality, int rotation, String outputPath,
final Callback successCb, final Callback failureCb) throws IOException {
Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.valueOf(compressFormatString);
if (imagePath.indexOf("data:image/") < 0) {
imagePath = imagePath.replace("file:", "");
if (imagePath.startsWith(ImageResizer.FILE_PREFIX)) {
imagePath = imagePath.replaceFirst(ImageResizer.FILE_PREFIX, "");
}
String resizedImagePath = ImageResizer.createResizedImage(this.context, imagePath, newWidth,
newHeight, compressFormat, quality, rotation, outputPath);
successCb.invoke("file:" + resizedImagePath);
// If resizedImagePath is empty and this wasn't caught earlier, throw.
if (resizedImagePath == null || resizedImagePath.isEmpty()) {
throw new IOException("Error getting resized image path");
}
// Invoke success, prepending file prefix.
successCb.invoke(ImageResizer.FILE_PREFIX + resizedImagePath);
}
}

View File

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="ResizerExample" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/drawee/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fbcore/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fresco/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.25.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/mockable-android-23.jar" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.25.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
<orderEntry type="module" module-name="react-native-image-resizer" exported="" />
</component>
</module>

View File

@ -17,7 +17,7 @@ public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}

View File

@ -6,9 +6,9 @@
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "^15.2.1",
"react-native": "^0.31.0",
"react": "^15.4.0",
"react-native": "^0.41.0",
"react-native-gifted-spinner": "0.0.4",
"react-native-image-resizer": "^0.0.8"
"react-native-image-resizer": "file:../"
}
}

View File

@ -19,7 +19,8 @@
"resize"
],
"peerDependencies": {
"react-native": ">=v0.14.2"
"react": "^15.4.0",
"react-native": ">=v0.40.0"
},
"author": "Florian Rival <florianr@bam.tech> (http://bam.tech)",
"license": "MIT",