diff --git a/app/build.gradle b/app/build.gradle index 427efee..a455070 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,8 +108,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_9 + targetCompatibility JavaVersion.VERSION_1_9 } namespace 'com.m2049r.xmrwallet' buildFeatures { @@ -135,7 +135,7 @@ dependencies { implementation 'com.google.android.material:material:1.6.0' - implementation 'me.dm7.barcodescanner:zxing:1.9.8' + implementation 'com.journeyapps:zxing-android-embedded:4.3.0' implementation "com.squareup.okhttp3:okhttp:4.9.3" implementation "io.github.rburgst:okhttp-digest:2.6" implementation "com.jakewharton.timber:timber:5.0.1" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 86fe305..3b2fc98 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,32 +1,11 @@ - - - - - - - - - - - - - - - - - - - - - - + barcodeLauncher = registerForActivityResult(new ScanContract(), + result -> { + if(result.getContents() != null) { + pasteAddress(result.getContents()); + } + }); + + private final ActivityResultLauncher cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), + granted -> { + if(granted) { + onScan(); + } else { + Toast.makeText(getActivity(), getString(R.string.no_camera_permission), Toast.LENGTH_SHORT).show(); + } + }); + private MutableLiveData _sendingMax = new MutableLiveData<>(false); public LiveData sendingMax = _sendingMax; private MutableLiveData _pendingTransaction = new MutableLiveData<>(null); @@ -41,6 +66,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { private Button sendButton; private Button sendMaxButton; private ImageButton pasteAddressImageButton; + private ImageButton scanAddressImageButton; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -51,6 +77,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); pasteAddressImageButton = view.findViewById(R.id.paste_address_imagebutton); + scanAddressImageButton = view.findViewById(R.id.scan_address_imagebutton); sendMaxButton = view.findViewById(R.id.send_max_button); addressEditText = view.findViewById(R.id.address_edittext); amountEditText = view.findViewById(R.id.amount_edittext); @@ -62,7 +89,14 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { amountTextView = view.findViewById(R.id.amount_pending_textview); pasteAddressImageButton.setOnClickListener(view1 -> { - addressEditText.setText(Helper.getClipBoardText(view.getContext())); + Context ctx = getContext(); + if(ctx != null) { + pasteAddress(Helper.getClipBoardText(getContext())); + } + }); + + scanAddressImageButton.setOnClickListener(view1 -> { + onScan(); }); sendMaxButton.setOnClickListener(view1 -> { @@ -127,6 +161,17 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { }); } + private void onScan() { + if (Helper.getCameraPermission(getActivity(), cameraPermissionsLauncher)) { + ScanOptions options = new ScanOptions(); + options.setBeepEnabled(false); + options.setOrientationLocked(true); + options.setDesiredBarcodeFormats(List.of(Intents.Scan.QR_CODE_MODE)); + options.addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.MIXED_SCAN); + barcodeLauncher.launch(options); + } + } + private void sendTx(PendingTransaction pendingTx) { AsyncTask.execute(() -> { boolean success = TxService.getInstance().sendTx(pendingTx); @@ -171,6 +216,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { createButton.setVisibility(View.GONE); sendMaxButton.setVisibility(View.GONE); pasteAddressImageButton.setVisibility(View.GONE); + scanAddressImageButton.setVisibility(View.GONE); feeTextView.setVisibility(View.VISIBLE); addressTextView.setVisibility(View.VISIBLE); amountTextView.setVisibility(View.VISIBLE); @@ -182,9 +228,20 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { createButton.setVisibility(View.VISIBLE); sendMaxButton.setVisibility(View.VISIBLE); pasteAddressImageButton.setVisibility(View.VISIBLE); + scanAddressImageButton.setVisibility(View.VISIBLE); feeTextView.setVisibility(View.GONE); addressTextView.setVisibility(View.GONE); amountTextView.setVisibility(View.GONE); } } + + private void pasteAddress(String address) { + String modifiedAddress = address.replace("monero:", "").split("\\?")[0]; + boolean isValid = Wallet.isAddressValid(modifiedAddress); + if(isValid) { + addressEditText.setText(modifiedAddress); + } else { + Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show(); + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java index d6532eb..e753ce7 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java @@ -41,6 +41,7 @@ import android.view.animation.AnimationUtils; import android.view.inputmethod.InputMethodManager; import android.widget.Toast; +import androidx.activity.result.ActivityResultLauncher; import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; @@ -114,6 +115,21 @@ public class Helper { } } + static public boolean getCameraPermission(Activity context, ActivityResultLauncher launcher) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + if (context.checkSelfPermission(Manifest.permission.CAMERA) + == PackageManager.PERMISSION_DENIED) { + Timber.w("Permission denied for CAMERA - requesting it"); + launcher.launch(Manifest.permission.CAMERA); + return false; + } else { + return true; + } + } else { + return true; + } + } + static public File getWalletFile(Context context, String aWalletName) { File walletDir = getWalletRoot(context); File f = new File(walletDir, aWalletName); diff --git a/app/src/main/res/drawable/ic_scan.xml b/app/src/main/res/drawable/ic_scan.xml index a06451e..3c23657 100644 --- a/app/src/main/res/drawable/ic_scan.xml +++ b/app/src/main/res/drawable/ic_scan.xml @@ -4,6 +4,6 @@ android:viewportWidth="30.0" android:viewportHeight="30.0"> diff --git a/app/src/main/res/layout/send_bottom_sheet_dialog.xml b/app/src/main/res/layout/send_bottom_sheet_dialog.xml index d18e9c3..8cca5b6 100644 --- a/app/src/main/res/layout/send_bottom_sheet_dialog.xml +++ b/app/src/main/res/layout/send_bottom_sheet_dialog.xml @@ -48,15 +48,32 @@ android:id="@+id/paste_address_imagebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:background="@android:color/transparent" + android:minWidth="48dp" + android:minHeight="48dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:padding="8dp" + android:src="@drawable/ic_content_paste_24dp" + app:layout_constraintBottom_toBottomOf="@id/address_edittext" + app:layout_constraintEnd_toStartOf="@id/scan_address_imagebutton" + app:layout_constraintStart_toEndOf="@id/address_edittext" + app:layout_constraintTop_toTopOf="@id/address_edittext" + tools:ignore="SpeakableTextPresentCheck" + tools:visibility="gone" /> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e116fa7..628dc91 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -571,4 +571,5 @@ Creating transaction… Sending transaction… Sent transaction! + No camera permission