Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
```
allprojects {
repositories {
jcenter()
...
maven { url "https://jitpack.io" }
}
}
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
buildscript {
ext {
androidx_appcompat_version = "1.1.0"
androidx_appcompat_version = "1.3.0"
androidx_core_version = "1.1.0"
androidx_exifinterface_version = "1.1.0-beta01"
androidx_transition_version = "1.2.0-rc01"
androidx_exifinterface_version = "1.3.2"
androidx_transition_version = "1.4.1"
constraintlayout_version = "1.1.3"
}

Expand Down
18 changes: 11 additions & 7 deletions sample/src/main/java/com/yalantis/ucrop/sample/ResultActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;

import com.yalantis.ucrop.util.BitmapLoadUtils;
import com.yalantis.ucrop.view.UCropView;

import java.io.File;
Expand All @@ -34,13 +42,6 @@
import java.util.Calendar;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;

import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION;

Expand Down Expand Up @@ -167,6 +168,9 @@ private void saveCroppedImage() {
Toast.makeText(ResultActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
Log.e(TAG, imageUri.toString(), e);
}
} else if (BitmapLoadUtils.hasContentScheme(imageUri)){
Toast.makeText(ResultActivity.this, getString(R.string.toast_already_saved), Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(ResultActivity.this, getString(R.string.toast_unexpected_error), Toast.LENGTH_SHORT).show();
}
Expand Down
1 change: 1 addition & 0 deletions sample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<string name="toast_cannot_retrieve_selected_image">Cannot retrieve selected image</string>
<string name="toast_cannot_retrieve_cropped_image">Cannot retrieve cropped image</string>
<string name="toast_unexpected_error">Unexpected error</string>
<string name="toast_already_saved">Your image is already saved</string>

<string name="file_provider_authorities">com.yalantis.ucrop.provider</string>
<string name="channel_name">ucrop_chanel</string>
Expand Down
55 changes: 31 additions & 24 deletions ucrop/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,27 +164,7 @@ private boolean crop() throws IOException {
if (shouldCrop) {
saveImage(Bitmap.createBitmap(mViewBitmap, cropOffsetX, cropOffsetY, mCroppedImageWidth, mCroppedImageHeight));
if (mCompressFormat.equals(Bitmap.CompressFormat.JPEG)) {
boolean hasImageInputUriContentSchema = hasContentScheme(mImageInputUri);
boolean hasImageOutputUriContentSchema = hasContentScheme(mImageOutputUri);
if (hasImageInputUriContentSchema && hasImageOutputUriContentSchema) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ImageHeaderParser.copyExif(context, mCroppedImageWidth, mCroppedImageHeight, mImageInputUri, mImageOutputUri);
} else {
Log.e(TAG, "It is not possible to write exif info into file represented by \"content\" Uri if Android < LOLLIPOP");
}
} else if (hasImageInputUriContentSchema) {
ImageHeaderParser.copyExif(context, mCroppedImageWidth, mCroppedImageHeight, mImageInputUri, mImageOutputPath);
} else if (hasImageOutputUriContentSchema) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ExifInterface originalExif = new ExifInterface(mImageInputPath);
ImageHeaderParser.copyExif(context, originalExif, mCroppedImageWidth, mCroppedImageHeight, mImageOutputUri);
} else {
Log.e(TAG, "It is not possible to write exif info into file represented by \"content\" Uri if Android < LOLLIPOP");
}
} else {
ExifInterface originalExif = new ExifInterface(mImageInputPath);
ImageHeaderParser.copyExif(originalExif, mCroppedImageWidth, mCroppedImageHeight, mImageOutputPath);
}
copyExifForOutputFile(context);
}
return true;
} else {
Expand All @@ -193,8 +173,35 @@ private boolean crop() throws IOException {
}
}

private boolean hasContentScheme(Uri uri) {
return uri != null && CONTENT_SCHEME.equals(uri.getScheme());
private void copyExifForOutputFile(Context context) throws IOException {
boolean hasImageInputUriContentSchema = BitmapLoadUtils.hasContentScheme(mImageInputUri);
boolean hasImageOutputUriContentSchema = BitmapLoadUtils.hasContentScheme(mImageOutputUri);
/*
* ImageHeaderParser.copyExif with output uri as a parameter
* uses ExifInterface constructor with FileDescriptor param for overriding output file exif info,
* which doesn't support ExitInterface.saveAttributes call for SDK lower than 21.
*
* See documentation for ImageHeaderParser.copyExif and ExifInterface.saveAttributes implementation.
*/
if (hasImageInputUriContentSchema && hasImageOutputUriContentSchema) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ImageHeaderParser.copyExif(context, mCroppedImageWidth, mCroppedImageHeight, mImageInputUri, mImageOutputUri);
} else {
Log.e(TAG, "It is not possible to write exif info into file represented by \"content\" Uri if Android < LOLLIPOP");
}
} else if (hasImageInputUriContentSchema) {
ImageHeaderParser.copyExif(context, mCroppedImageWidth, mCroppedImageHeight, mImageInputUri, mImageOutputPath);
} else if (hasImageOutputUriContentSchema) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ExifInterface originalExif = new ExifInterface(mImageInputPath);
ImageHeaderParser.copyExif(context, originalExif, mCroppedImageWidth, mCroppedImageHeight, mImageOutputUri);
} else {
Log.e(TAG, "It is not possible to write exif info into file represented by \"content\" Uri if Android < LOLLIPOP");
}
} else {
ExifInterface originalExif = new ExifInterface(mImageInputPath);
ImageHeaderParser.copyExif(originalExif, mCroppedImageWidth, mCroppedImageHeight, mImageOutputPath);
}
}

private void saveImage(@NonNull Bitmap croppedBitmap) {
Expand Down Expand Up @@ -244,7 +251,7 @@ protected void onPostExecute(@Nullable Throwable t) {
if (t == null) {
Uri uri;

if (hasContentScheme(mImageOutputUri)) {
if (BitmapLoadUtils.hasContentScheme(mImageOutputUri)) {
uri = mImageOutputUri;
} else {
uri = Uri.fromFile(new File(mImageOutputPath));
Expand Down
14 changes: 10 additions & 4 deletions ucrop/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@
import android.view.Display;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.exifinterface.media.ExifInterface;

import com.yalantis.ucrop.callback.BitmapLoadCallback;
import com.yalantis.ucrop.task.BitmapLoadTask;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.exifinterface.media.ExifInterface;

/**
* Created by Oleksii Shliama (https://github.com/shliama).
*/
public class BitmapLoadUtils {

private static final String CONTENT_SCHEME = "content";

private static final String TAG = "BitmapLoadUtils";

public static void decodeBitmapInBackground(@NonNull Context context,
Expand Down Expand Up @@ -171,4 +173,8 @@ public static void close(@Nullable Closeable c) {
}
}

public static boolean hasContentScheme(Uri uri) {
return uri != null && CONTENT_SCHEME.equals(uri.getScheme());
}

}