mirror of
https://codeberg.org/anoncontributorxmr/mysu.git
synced 2024-11-22 07:22:26 +00:00
add ability to scan QR codes
This commit is contained in:
parent
fcadb39b76
commit
4089e22bc5
7 changed files with 104 additions and 29 deletions
|
@ -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"
|
||||
|
|
|
@ -1,32 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.m2049r.xmrwallet">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="org.torproject.android.intent.action.START" />
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.torproject.android.intent.action.STATUS" />
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="org.torproject.android.REQUEST_V3_ONION_SERVICE" />
|
||||
</intent>
|
||||
|
||||
<package android:name="org.torproject.android" />
|
||||
</queries>
|
||||
|
||||
<application
|
||||
android:name=".MoneroApplication"
|
||||
|
@ -46,6 +25,11 @@
|
|||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.journeyapps.barcodescanner.CaptureActivity"
|
||||
android:screenOrientation="portrait"
|
||||
tools:replace="android:screenOrientation"
|
||||
android:stateNotNeeded="true"/>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package com.m2049r.xmrwallet.fragment.dialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
import com.google.zxing.client.android.Intents;
|
||||
import com.journeyapps.barcodescanner.ScanContract;
|
||||
import com.journeyapps.barcodescanner.ScanOptions;
|
||||
import com.m2049r.xmrwallet.R;
|
||||
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
|
@ -20,12 +25,32 @@ import android.widget.ImageButton;
|
|||
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.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SendBottomSheetDialog extends BottomSheetDialogFragment {
|
||||
private final ActivityResultLauncher<ScanOptions> barcodeLauncher = registerForActivityResult(new ScanContract(),
|
||||
result -> {
|
||||
if(result.getContents() != null) {
|
||||
pasteAddress(result.getContents());
|
||||
}
|
||||
});
|
||||
|
||||
private final ActivityResultLauncher<String> 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<Boolean> _sendingMax = new MutableLiveData<>(false);
|
||||
public LiveData<Boolean> sendingMax = _sendingMax;
|
||||
private MutableLiveData<PendingTransaction> _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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<String> 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);
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
android:viewportWidth="30.0"
|
||||
android:viewportHeight="30.0">
|
||||
<path
|
||||
android:fillColor="?attr/colorPrimaryVariant"
|
||||
android:fillColor="@color/oled_textColorPrimary"
|
||||
android:pathData="M26.667,27.996L27.991,26.667L27.991,20L30,20L30,26.667C30,28.5 28.5,30 26.667,30L20,30L20,27.996L26.667,27.996ZM3.333,27.996L10,27.996L10,30L3.333,30C1.5,30 0,28.5 0,26.667L0,20L2.009,20L2.009,26.667L3.333,27.996ZM26.667,2.004L20,2.004L20,0L26.667,0C28.5,0 30,1.5 30,3.333L30,10L27.991,10L27.991,3.333L26.667,2.004ZM3.333,2.004L2.009,3.333L2.009,10L0,10L0,3.333C0,1.5 1.5,0 3.333,0L10,0L10,2.004L3.333,2.004Z" />
|
||||
</vector>
|
||||
|
|
|
@ -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" />
|
||||
<ImageButton
|
||||
android:id="@+id/scan_address_imagebutton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:minWidth="48dp"
|
||||
android:minHeight="48dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_content_paste_24dp"
|
||||
android:src="@drawable/ic_scan"
|
||||
app:layout_constraintBottom_toBottomOf="@id/address_edittext"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/address_edittext"
|
||||
app:layout_constraintStart_toEndOf="@id/paste_address_imagebutton"
|
||||
app:layout_constraintTop_toTopOf="@id/address_edittext"
|
||||
tools:ignore="SpeakableTextPresentCheck"
|
||||
tools:visibility="gone" />
|
||||
|
|
|
@ -571,4 +571,5 @@
|
|||
<string name="creating_tx">Creating transaction…</string>
|
||||
<string name="sending_tx">Sending transaction…</string>
|
||||
<string name="sent_tx">Sent transaction!</string>
|
||||
<string name="no_camera_permission">No camera permission</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue