559: #372 image rotation and crop r=TheLastProject a=Kethen

`@waffshappen` suggested https://github.com/Yalantis/uCrop
targets #372



https://user-images.githubusercontent.com/22017945/139484703-e33a5da8-ccb5-4d6a-b70c-3325e34fcec9.mp4

 


Co-authored-by: Katharine <kwchuiaa@connect.ust.hk>
This commit is contained in:
bors[bot]
2021-11-06 13:25:39 +00:00
committed by GitHub
6 changed files with 313 additions and 103 deletions

View File

@@ -85,6 +85,7 @@ dependencies {
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'com.github.yalantis:ucrop:2.2.6'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
// Splash Screen

View File

@@ -115,6 +115,10 @@
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"/>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"

View File

@@ -2,6 +2,7 @@ package protect.card_locker;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
@@ -12,13 +13,10 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.LocaleList;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.InputType;
import android.util.Log;
@@ -36,6 +34,16 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -43,6 +51,8 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import com.jaredrummler.android.colorpicker.ColorPickerDialog;
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener;
import com.yalantis.ucrop.UCrop;
import com.yalantis.ucrop.model.AspectRatio;
import java.io.File;
import java.io.FileNotFoundException;
@@ -63,14 +73,6 @@ import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.DialogFragment;
import protect.card_locker.async.TaskHandler;
public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
@@ -78,6 +80,21 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
private final String STATE_TAB_INDEX = "savedTab";
private final String STATE_TEMP_CARD = "tempLoyaltyCard";
private final String STATE_REQUESTED_IMAGE = "requestedImage";
private final String STATE_FRONT_IMAGE_UNSAVED = "frontImageUnsaved";
private final String STATE_BACK_IMAGE_UNSAVED = "backImageUnsaved";
private final String STATE_UPDATE_LOYALTY_CARD = "updateLoyaltyCard";
private final String STATE_HAS_CHANGED = "hasChange";
private final String STATE_FRONT_IMAGE_REMOVED = "frontImageRemoved";
private final String STATE_BACK_IMAGE_REMOVED = "backImageRemoved";
private final String TEMP_CAMERA_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_camera_image.jpg";
private final String TEMP_CROP_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_crop_image.png";
private final Bitmap.CompressFormat TEMP_CROP_IMAGE_FORMAT = Bitmap.CompressFormat.PNG;
private final String TEMP_UNSAVED_FRONT_IMAGE_NAME = LoyaltyCardEditActivity.class.getSimpleName() + "_front_image.png";
private final String TEMP_UNSAVED_BACK_IMAGE_NAME= LoyaltyCardEditActivity.class.getSimpleName() + "_back_image.png";
private final Bitmap.CompressFormat TEMP_UNSAVED_IMAGE_FORMAT = Bitmap.CompressFormat.PNG;
private static final int ID_IMAGE_FRONT = 0;
private static final int ID_IMAGE_BACK = 1;
@@ -137,10 +154,23 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
HashMap<String, Currency> currencies = new HashMap<>();
String tempCameraPicturePath;
LoyaltyCard tempLoyaltyCard;
ActivityResultLauncher<Uri> mPhotoTakerLauncher;
ActivityResultLauncher<Intent> mPhotoPickerLauncher;
ActivityResultLauncher<Intent> mCardIdAndBarCodeEditorLauncher;
ActivityResultLauncher<Intent> mCropperLauncher;
int mRequestedImage = 0;
int mCropperFinishedType = 0;
UCrop.Options mCropperOptions;
boolean mFrontImageUnsaved = false;
boolean mBackImageUnsaved = false;
boolean mFrontImageRemoved = false;
boolean mBackImageRemoved = false;
final private TaskHandler mTasks = new TaskHandler();
private static LoyaltyCard updateTempState(LoyaltyCard loyaltyCard, LoyaltyCardField fieldName, Object value) {
@@ -182,12 +212,31 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
+ ", updateLoyaltyCard=" + updateLoyaltyCard);
}
@Override
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
tabs = findViewById(R.id.tabs);
savedInstanceState.putInt(STATE_TAB_INDEX, tabs.getSelectedTabPosition());
savedInstanceState.putParcelable(STATE_TEMP_CARD, tempLoyaltyCard);
savedInstanceState.putInt(STATE_REQUESTED_IMAGE, mRequestedImage);
Object cardImageFrontObj = cardImageFront.getTag();
if (mFrontImageUnsaved && (cardImageFrontObj instanceof Bitmap) && Utils.saveTempImage(this, (Bitmap)cardImageFrontObj, TEMP_UNSAVED_FRONT_IMAGE_NAME, TEMP_UNSAVED_IMAGE_FORMAT) != null){
savedInstanceState.putInt(STATE_FRONT_IMAGE_UNSAVED, 1);
}else{
savedInstanceState.putInt(STATE_FRONT_IMAGE_UNSAVED, 0);
}
Object cardImageBackObj = cardImageBack.getTag();
if (mBackImageUnsaved && (cardImageBackObj instanceof Bitmap) && Utils.saveTempImage(this, (Bitmap)cardImageBackObj, TEMP_UNSAVED_BACK_IMAGE_NAME, TEMP_UNSAVED_IMAGE_FORMAT) != null){
savedInstanceState.putInt(STATE_BACK_IMAGE_UNSAVED, 1);
}else{
savedInstanceState.putInt(STATE_BACK_IMAGE_UNSAVED, 0);
}
savedInstanceState.putInt(STATE_UPDATE_LOYALTY_CARD, updateLoyaltyCard ? 1 : 0);
savedInstanceState.putInt(STATE_HAS_CHANGED, hasChanged ? 1 : 0);
savedInstanceState.putInt(STATE_FRONT_IMAGE_REMOVED, mFrontImageRemoved ? 1 : 0);
savedInstanceState.putInt(STATE_BACK_IMAGE_REMOVED, mBackImageRemoved ? 1 : 0);
}
@Override
@@ -196,6 +245,13 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
super.onRestoreInstanceState(savedInstanceState);
tabs = findViewById(R.id.tabs);
tabs.selectTab(tabs.getTabAt(savedInstanceState.getInt(STATE_TAB_INDEX)));
mRequestedImage = savedInstanceState.getInt(STATE_REQUESTED_IMAGE);
mFrontImageUnsaved = savedInstanceState.getInt(STATE_FRONT_IMAGE_UNSAVED) == 1;
mBackImageUnsaved = savedInstanceState.getInt(STATE_BACK_IMAGE_UNSAVED) == 1;
updateLoyaltyCard = savedInstanceState.getInt(STATE_UPDATE_LOYALTY_CARD) == 1;
hasChanged = savedInstanceState.getInt(STATE_HAS_CHANGED) == 1;
mFrontImageRemoved = savedInstanceState.getInt(STATE_FRONT_IMAGE_REMOVED) == 1;
mBackImageRemoved = savedInstanceState.getInt(STATE_BACK_IMAGE_REMOVED) == 1;
}
@Override
@@ -417,7 +473,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
if (!lastValue.toString().equals(getString(R.string.setBarcodeId))) {
barcodeIdField.setText(lastValue);
}
;
AlertDialog.Builder builder = new AlertDialog.Builder(LoyaltyCardEditActivity.this);
builder.setTitle(R.string.setBarcodeId);
@@ -509,6 +564,108 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
});
tabs.selectTab(tabs.getTabAt(0));
mPhotoTakerLauncher = registerForActivityResult(new ActivityResultContracts.TakePicture(), result->{
if (result) {
startCropper(getCacheDir() + "/" + TEMP_CAMERA_IMAGE_NAME);
}
});
// android 11: wanted to swap it to ActivityResultContracts.GetContent but then it shows a file browsers that shows image mime types, offering gallery in the file browser
mPhotoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == RESULT_OK) {
Intent intent = result.getData();
if (intent == null){
Log.d("photo picker", "photo picker returned without an intent");
return;
}
Uri uri = intent.getData();
startCropperUri(uri);
}
});
mCardIdAndBarCodeEditorLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == RESULT_OK) {
Intent intent = result.getData();
if (intent == null){
Log.d("barcode card id editor", "barcode and card id editor picker returned without an intent");
return;
}
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(Utils.BARCODE_SCAN, result.getResultCode(), intent, getApplicationContext());
cardId = barcodeValues.content();
barcodeType = barcodeValues.format();
barcodeId = "";
}
});
mCropperLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
Intent intent = result.getData();
if (intent == null){
Log.d("cropper", "ucrop returned a null intent");
return;
}
if (result.getResultCode() == Activity.RESULT_OK) {
Uri debugUri = UCrop.getOutput(intent);
if (debugUri == null){
throw new RuntimeException("ucrop returned success but not destination uri!");
}
Log.d("cropper", "ucrop produced image at " + debugUri);
Bitmap bitmap = BitmapFactory.decodeFile(getCacheDir() + "/" + TEMP_CROP_IMAGE_NAME);
if (bitmap != null) {
bitmap = Utils.resizeBitmap(bitmap);
if (requestedFrontImage()) {
mFrontImageUnsaved = true;
setCardImage(cardImageFront, bitmap);
} else {
mBackImageUnsaved = true;
setCardImage(cardImageBack, bitmap);
}
Log.d("cropper", "mRequestedImage: " + mRequestedImage);
mCropperFinishedType = mRequestedImage;
hasChanged = true;
} else {
Toast.makeText(LoyaltyCardEditActivity.this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
}
}else if(result.getResultCode() == UCrop.RESULT_ERROR){
Throwable e = UCrop.getError(intent);
if (e == null){
throw new RuntimeException("ucrop returned error state but not an error!");
}
Log.e("cropper error", e.toString());
}
});
mCropperOptions = new UCrop.Options();
setCropperTheme();
}
// ucrop 2.2.6 initial aspect ratio is glitched when 0x0 is used as the initial ratio option
// https://github.com/Yalantis/uCrop/blob/281c8e6438d81f464d836fc6b500517144af264a/ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java#L264
// so source width height has to be provided for now, depending on whether future versions of ucrop will support 0x0 as the default option
private void setCropperOptions(float sourceWidth, float sourceHeight){
mCropperOptions.setCompressionFormat(TEMP_CROP_IMAGE_FORMAT);
mCropperOptions.setFreeStyleCropEnabled(true);
mCropperOptions.setHideBottomControls(false);
// default aspect ratio workaround
int selectedByDefault = 1;
if (sourceWidth == 0f && sourceHeight == 0f){
selectedByDefault = 0;
}
mCropperOptions.setAspectRatioOptions(selectedByDefault,
new AspectRatio(null, 1, 1),
new AspectRatio(getResources().getString(R.string.ucrop_label_original).toUpperCase(), sourceWidth, sourceHeight),
new AspectRatio(getResources().getString(R.string.card),85.6f,53.98f )
);
}
private void setCropperTheme(){
mCropperOptions.setToolbarColor(getResources().getColor(R.color.colorPrimary));
mCropperOptions.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
mCropperOptions.setToolbarWidgetColor(Color.WHITE);
mCropperOptions.setActiveControlsWidgetColor(getResources().getColor(R.color.colorPrimary));
}
@Override
@@ -519,6 +676,18 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
extractIntentFields(intent);
}
private boolean requestedFrontImage(){
return mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_FRONT;
}
private boolean croppedFrontImage(){
return mCropperFinishedType == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || mCropperFinishedType == Utils.CARD_IMAGE_FROM_FILE_FRONT;
}
private boolean croppedBackImage(){
return mCropperFinishedType == Utils.CARD_IMAGE_FROM_CAMERA_BACK || mCropperFinishedType == Utils.CARD_IMAGE_FROM_FILE_BACK;
}
@SuppressLint("DefaultLocale")
@Override
public void onResume() {
@@ -528,6 +697,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
onResuming = true;
if (tempLoyaltyCard == null) {
if (updateLoyaltyCard) {
tempLoyaltyCard = db.getLoyaltyCard(loyaltyCardId);
@@ -537,9 +707,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
finish();
return;
}
setTitle(R.string.editCardTitle);
setCardImage(cardImageFront, Utils.retrieveCardImage(this, tempLoyaltyCard.id, true));
setCardImage(cardImageBack, Utils.retrieveCardImage(this, tempLoyaltyCard.id, false));
} else if (importLoyaltyCardUri != null) {
try {
tempLoyaltyCard = importUriHelper.parse(importLoyaltyCardUri);
@@ -548,14 +715,37 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
finish();
return;
}
setTitle(R.string.addCardTitle);
} else {
// New card, use default values
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(),100);
setTitle(R.string.addCardTitle);
}
}
if(!initDone) {
if (updateLoyaltyCard) {
setTitle(R.string.editCardTitle);
if (!mFrontImageUnsaved && !croppedFrontImage() && !mFrontImageRemoved) {
setCardImage(cardImageFront, Utils.retrieveCardImage(this, tempLoyaltyCard.id, true));
}
if (!mBackImageUnsaved && !croppedBackImage() && !mBackImageRemoved) {
setCardImage(cardImageBack, Utils.retrieveCardImage(this, tempLoyaltyCard.id, false));
}
}else{
setTitle(R.string.addCardTitle);
}
if(mFrontImageUnsaved && !croppedFrontImage()){
setCardImage(cardImageFront, Utils.loadTempImage(this, TEMP_UNSAVED_FRONT_IMAGE_NAME));
}
if(mBackImageUnsaved && !croppedBackImage()){
setCardImage(cardImageBack, Utils.loadTempImage(this, TEMP_UNSAVED_BACK_IMAGE_NAME));
}
}
mCropperFinishedType = 0;
boolean hadChanges = hasChanged;
storeFieldEdit.setText(tempLoyaltyCard.store);
noteFieldEdit.setText(tempLoyaltyCard.note);
formatExpiryField(this, expiryField, tempLoyaltyCard.expiry);
@@ -645,8 +835,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
// Initialization has finished
if (!initDone) {
hasChanged = false;
initDone = true;
hasChanged = hadChanges;
}
generateOrHideBarcode();
@@ -786,22 +976,13 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
confirmExitDialog.show();
}
private void takePhotoForCard(int type) throws IOException {
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoURI = FileProvider.getUriForFile(LoyaltyCardEditActivity.this, BuildConfig.APPLICATION_ID, Utils.createTempFile(this, TEMP_CAMERA_IMAGE_NAME));
mRequestedImage = type;
String imageFileName = "CATIMA_" + new Date().getTime();
File image = File.createTempFile(
imageFileName,
".jpg",
getExternalFilesDir(Environment.DIRECTORY_PICTURES)
);
tempCameraPicturePath = image.getAbsolutePath();
Uri photoURI = FileProvider.getUriForFile(LoyaltyCardEditActivity.this, BuildConfig.APPLICATION_ID, image);
i.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(i, type);
mPhotoTakerLauncher.launch(photoURI);
}
class EditCardIdAndBarcode implements View.OnClickListener {
@@ -811,7 +992,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
final Bundle b = new Bundle();
b.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, cardIdFieldView.getText().toString());
i.putExtras(b);
startActivityForResult(i, Utils.BARCODE_SCAN);
mCardIdAndBarCodeEditorLauncher.launch(i);
}
}
@@ -824,6 +1005,13 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
if (targetView.getTag() != null) {
cardOptions.put(getString(R.string.removeImage), () -> {
setCardImage(targetView, null);
if (targetView == cardImageFront){
mFrontImageRemoved = true;
mFrontImageUnsaved = false;
}else{
mBackImageRemoved = true;
mBackImageUnsaved = false;
}
return null;
});
}
@@ -840,7 +1028,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
cardOptions.put(getString(R.string.addFromImage), () -> {
Intent i = new Intent(Intent.ACTION_PICK);
i.setType("image/*");
startActivityForResult(i, v.getId() == ID_IMAGE_FRONT ? Utils.CARD_IMAGE_FROM_FILE_FRONT : Utils.CARD_IMAGE_FROM_FILE_BACK);
mRequestedImage = v.getId() == ID_IMAGE_FRONT ? Utils.CARD_IMAGE_FROM_FILE_FRONT : Utils.CARD_IMAGE_FROM_FILE_BACK;
mPhotoPickerLauncher.launch(i);
return null;
});
@@ -1035,68 +1224,55 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
public void startCropper(String sourceImagePath){
startCropperUri(Uri.parse("file://" + sourceImagePath));
}
public void startCropperUri(Uri sourceUri){
Log.d("cropper", "launching cropper with image " + sourceUri.getPath());
File cropOutput = Utils.createTempFile(this, TEMP_CROP_IMAGE_NAME);
Uri destUri = Uri.parse("file://" + cropOutput.getAbsolutePath());
Log.d("cropper", "asking cropper to output to " + destUri.toString());
if (resultCode == RESULT_OK) {
if (requestCode == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || requestCode == Utils.CARD_IMAGE_FROM_CAMERA_BACK) {
Bitmap bitmap = BitmapFactory.decodeFile(tempCameraPicturePath);
if(mRequestedImage == Utils.CARD_IMAGE_FROM_CAMERA_FRONT || mRequestedImage == Utils.CARD_IMAGE_FROM_FILE_FRONT){
mCropperOptions.setToolbarTitle(getResources().getString(R.string.setFrontImage));
}else{
mCropperOptions.setToolbarTitle(getResources().getString(R.string.setBackImage));
}
if (bitmap != null) {
bitmap = Utils.resizeBitmap(bitmap);
try {
bitmap = Utils.rotateBitmap(bitmap, new ExifInterface(tempCameraPicturePath));
} catch (IOException e) {
e.printStackTrace();
}
if (requestCode == Utils.CARD_IMAGE_FROM_CAMERA_FRONT) {
setCardImage(cardImageFront, bitmap);
} else {
setCardImage(cardImageBack, bitmap);
}
hasChanged = true;
} else {
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
}
} else if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT || requestCode == Utils.CARD_IMAGE_FROM_FILE_BACK) {
Bitmap bitmap = null;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ImageDecoder.Source image_source = ImageDecoder.createSource(getContentResolver(), intent.getData());
bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
} else {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), intent.getData());
}
} catch (IOException e) {
Log.e(TAG, "Error getting data from image file");
e.printStackTrace();
}
if (bitmap != null) {
bitmap = Utils.resizeBitmap(bitmap);
if (requestCode == Utils.CARD_IMAGE_FROM_FILE_FRONT) {
setCardImage(cardImageFront, bitmap);
} else {
setCardImage(cardImageBack, bitmap);
}
hasChanged = true;
} else {
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
}
} else {
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
cardId = barcodeValues.content();
barcodeType = barcodeValues.format();
barcodeId = "";
// sniff the input image for width and height to work around a ucrop bug
Bitmap image = null;
try {
image = BitmapFactory.decodeStream(getContentResolver().openInputStream(sourceUri));
}catch(FileNotFoundException e){
e.printStackTrace();
Log.d("cropper", "failed opening bitmap for initial width and height for ucrop " + sourceUri.toString());
}
if (image == null){
Log.d("cropper", "failed loading bitmap for initial width and height for ucrop " + sourceUri.toString());
setCropperOptions(0f, 0f);
}else{
try {
Bitmap imageRotated = Utils.rotateBitmap(image, new ExifInterface(getContentResolver().openInputStream(sourceUri)));
setCropperOptions(imageRotated.getWidth(), imageRotated.getHeight());
}catch(FileNotFoundException e){
e.printStackTrace();
Log.d("cropper", "failed opening image for exif reading before setting initial width and height for ucrop");
setCropperOptions(image.getWidth(), image.getHeight());
}catch(IOException e){
e.printStackTrace();
Log.d("cropper", "exif reading failed before setting initial width and height for ucrop");
setCropperOptions(image.getWidth(), image.getHeight());
}
}
onResume();
mCropperLauncher.launch(
UCrop.of(
sourceUri,
destUri
).withOptions(mCropperOptions)
.getIntent(this)
);
return;
}
private void showBarcode() {

View File

@@ -25,6 +25,7 @@ import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -410,10 +411,37 @@ public class Utils {
Configuration config = inputContext.getResources().getConfiguration();
int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
return (currentNightMode == Configuration.UI_MODE_NIGHT_YES);
}else if (nightModeSetting == AppCompatDelegate.MODE_NIGHT_YES){
return true;
}else{
return false;
}else {
return nightModeSetting == AppCompatDelegate.MODE_NIGHT_YES;
}
}
public static File createTempFile(Context context, String name){
return new File(context.getCacheDir() + "/" + name);
}
public static String saveTempImage(Context context, Bitmap in, String name, Bitmap.CompressFormat format){
File image = createTempFile(context, name);
try (FileOutputStream out = new FileOutputStream(image)){
in.compress(format, 100, out);
return image.getAbsolutePath();
}catch(IOException e){
Log.d("store temp image", "failed writing temp file for temporary image, name: " + name);
return null;
}
}
public static Bitmap loadImage(String path){
try{
return BitmapFactory.decodeStream(new FileInputStream(path));
}catch(IOException e){
Log.d("load image", "failed loading image from " + path);
return null;
}
}
public static Bitmap loadTempImage(Context context, String name){
return loadImage(context.getCacheDir() + "/" + name);
}
}

View File

@@ -1,3 +1,3 @@
<paths>
<external-path name="exportPath" path="/" />
<cache-path name="cachePath" path="/" />
</paths>

View File

@@ -263,11 +263,6 @@ public class LoyaltyCardViewActivityTest
assertNotNull(intent);
assertEquals(intent.getComponent().getClassName(), ScanActivity.class.getCanonicalName());
Activity newActivity = Robolectric.buildActivity(ScanActivity.class, intent).create().get();
final Button manualButton = newActivity.findViewById(R.id.add_manually);
manualButton.performClick();
intentForResult = shadowOf(activity).peekNextStartedActivityForResult();
assertNotNull(intentForResult);
@@ -516,6 +511,7 @@ public class LoyaltyCardViewActivityTest
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
activityController.resume();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
@@ -540,6 +536,7 @@ public class LoyaltyCardViewActivityTest
// Complete barcode capture in failure
captureBarcodeWithResult(activity, false);
activityController.resume();
shadowOf(getMainLooper()).idle();
@@ -561,6 +558,7 @@ public class LoyaltyCardViewActivityTest
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
activityController.resume();
checkAllFields(activity, ViewMode.ADD_CARD, "", "", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
@@ -660,6 +658,7 @@ public class LoyaltyCardViewActivityTest
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
@@ -684,6 +683,7 @@ public class LoyaltyCardViewActivityTest
// Complete barcode capture successfully
captureBarcodeWithResult(activity, true);
activityController.resume();
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), BARCODE_TYPE.prettyName(), null, null);
@@ -1136,6 +1136,7 @@ public class LoyaltyCardViewActivityTest
// Complete empty barcode selection successfully
selectBarcodeWithResult(activity, BARCODE_DATA, "", true);
activityController.resume();
// Check if the barcode type is NO_BARCODE as expected
checkAllFields(activity, ViewMode.UPDATE_CARD, "store", "note", context.getString(R.string.never), "0", context.getString(R.string.points), BARCODE_DATA, context.getString(R.string.sameAsCardId), context.getString(R.string.noBarcode), null, null);