mirror of https://github.com/m2049r/xmrwallet.git
QR scan of amount as well
bugfix: use getSupportFragmentManager everywhere
This commit is contained in:
parent
20dbaac4fa
commit
6822aa83d8
|
@ -308,7 +308,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
void popFragmentStack(String name) {
|
void popFragmentStack(String name) {
|
||||||
getFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
|
@ -28,8 +28,7 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
|
||||||
|
|
||||||
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||||
|
|
||||||
|
@ -39,9 +38,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
||||||
Listener activityCallback;
|
Listener activityCallback;
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onAddressScanned(String address, String paymentId);
|
boolean onAddressScanned(String uri);
|
||||||
|
|
||||||
boolean isPaymentIdValid(String paymentId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZXingScannerView mScannerView;
|
private ZXingScannerView mScannerView;
|
||||||
|
@ -61,32 +58,16 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
||||||
mScannerView.startCamera();
|
mScannerView.startCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String URI_PREFIX = "monero:";
|
static final String QR_SCHEME = "monero:";
|
||||||
static final String PAYMENTID_STRING = "?tx_payment_id=";
|
static final String QR_PAYMENTID = "tx_payment_id";
|
||||||
|
static final String QR_AMOUNT = "tx_amount";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(Result rawResult) {
|
public void handleResult(Result rawResult) {
|
||||||
Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
|
//Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
|
||||||
String text = rawResult.getText();
|
|
||||||
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
||||||
(text.startsWith(URI_PREFIX))) {
|
(rawResult.getText().startsWith(QR_SCHEME))) {
|
||||||
String address = null;
|
if (activityCallback.onAddressScanned(rawResult.getText())) {
|
||||||
String paymentId = null;
|
|
||||||
String s = text.substring(URI_PREFIX.length());
|
|
||||||
if (s.length() == 95) {
|
|
||||||
address = s;
|
|
||||||
} else {
|
|
||||||
int i = s.indexOf(PAYMENTID_STRING);
|
|
||||||
if ((i == 95) && (s.length() == (95 + PAYMENTID_STRING.length() + 16))) {
|
|
||||||
address = s.substring(0, 95);
|
|
||||||
paymentId = s.substring(95 + PAYMENTID_STRING.length());
|
|
||||||
if (!activityCallback.isPaymentIdValid(paymentId)) {
|
|
||||||
address = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Helper.isAddressOk(address, WalletManager.getInstance().isTestNet())) {
|
|
||||||
activityCallback.onAddressScanned(address, paymentId);
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
||||||
|
@ -120,7 +101,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
Log.d(TAG, "attaching scan");
|
//Log.d(TAG, "attaching scan");
|
||||||
if (context instanceof Listener) {
|
if (context instanceof Listener) {
|
||||||
this.activityCallback = (Listener) context;
|
this.activityCallback = (Listener) context;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -373,26 +373,40 @@ public class SendFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
Log.d(TAG, "onResume");
|
||||||
BarcodeData data = activityCallback.getScannedData();
|
BarcodeData data = activityCallback.getScannedData();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
String scannedAddress = data.address;
|
String scannedAddress = data.address;
|
||||||
if (scannedAddress != null) {
|
if (scannedAddress != null) {
|
||||||
etAddress.setText(scannedAddress);
|
etAddress.setText(scannedAddress);
|
||||||
|
} else {
|
||||||
|
etAddress.getText().clear();
|
||||||
}
|
}
|
||||||
String scannedPaymenId = data.paymentId;
|
String scannedPaymenId = data.paymentId;
|
||||||
if (scannedPaymenId != null) {
|
if (scannedPaymenId != null) {
|
||||||
etPaymentId.setText(scannedPaymenId);
|
etPaymentId.setText(scannedPaymenId);
|
||||||
|
} else {
|
||||||
|
etPaymentId.getText().clear();
|
||||||
|
}
|
||||||
|
if (data.amount >= 0) {
|
||||||
|
String scannedAmount = Helper.getDisplayAmount(data.amount);
|
||||||
|
etAmount.setText(scannedAmount);
|
||||||
|
} else {
|
||||||
|
etAmount.getText().clear();
|
||||||
|
}
|
||||||
|
etAmount.requestFocus();
|
||||||
|
etAmount.setSelection(etAmount.getText().length());
|
||||||
|
} else { // no scan data
|
||||||
|
// jump to first empty field
|
||||||
|
if (etAddress.getText().toString().isEmpty()) {
|
||||||
|
etAddress.requestFocus();
|
||||||
|
} else if (etPaymentId.getText().toString().isEmpty()) {
|
||||||
|
etPaymentId.requestFocus();
|
||||||
|
} else {
|
||||||
|
etAmount.requestFocus();
|
||||||
|
etAmount.setSelection(etAmount.getText().length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// jump to first empty field
|
|
||||||
if (etAddress.getText().toString().isEmpty()) {
|
|
||||||
etAddress.requestFocus();
|
|
||||||
} else if (etPaymentId.getText().toString().isEmpty()) {
|
|
||||||
etPaymentId.requestFocus();
|
|
||||||
} else {
|
|
||||||
etAmount.requestFocus();
|
|
||||||
}
|
|
||||||
Log.d(TAG, "onResume");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,6 +21,8 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.net.UrlQuerySanitizer;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
@ -45,6 +47,9 @@ import com.m2049r.xmrwallet.util.BarcodeData;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.TxData;
|
import com.m2049r.xmrwallet.util.TxData;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
|
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
|
||||||
WalletService.Observer, SendFragment.Listener, TxFragment.Listener,
|
WalletService.Observer, SendFragment.Listener, TxFragment.Listener,
|
||||||
GenerateReviewFragment.ListenerWithWallet,
|
GenerateReviewFragment.ListenerWithWallet,
|
||||||
|
@ -563,7 +568,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPaymentIdValid(String paymentId) {
|
public boolean isPaymentIdValid(String paymentId) {
|
||||||
return getWallet().isPaymentIdValid(paymentId);
|
return Wallet.isPaymentIdValid(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -573,9 +578,9 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||||
|
|
||||||
void popFragmentStack(String name) {
|
void popFragmentStack(String name) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
getFragmentManager().popBackStack();
|
getSupportFragmentManager().popBackStack();
|
||||||
} else {
|
} else {
|
||||||
getFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,12 +631,61 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||||
private BarcodeData scannedData = null;
|
private BarcodeData scannedData = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAddressScanned(String address, String paymentId) {
|
public boolean onAddressScanned(String uri) {
|
||||||
// Log.d(TAG, "got " + address);
|
BarcodeData bcData = parseMoneroUri(uri);
|
||||||
scannedData = new BarcodeData(address, paymentId);
|
if (bcData != null) {
|
||||||
popFragmentStack(null);
|
this.scannedData = bcData;
|
||||||
|
popFragmentStack(null);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse and decode a monero scheme string. It is here because it needs to validate the data.
|
||||||
|
*
|
||||||
|
* @param uri String containing a monero URL
|
||||||
|
* @return BarcodeData object or null if uri not valid
|
||||||
|
*/
|
||||||
|
public BarcodeData parseMoneroUri(String uri) {
|
||||||
|
if (uri == null) return null;
|
||||||
|
|
||||||
|
if (!uri.startsWith(ScannerFragment.QR_SCHEME)) return null;
|
||||||
|
|
||||||
|
String noScheme = uri.substring(ScannerFragment.QR_SCHEME.length());
|
||||||
|
Uri monero = Uri.parse(noScheme);
|
||||||
|
Map<String, String> parms = new HashMap<>();
|
||||||
|
String query = monero.getQuery();
|
||||||
|
if (query != null) {
|
||||||
|
String[] args = query.split("&");
|
||||||
|
for (String arg : args) {
|
||||||
|
String[] namevalue = arg.split("=");
|
||||||
|
if (namevalue.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
|
||||||
|
namevalue.length > 1 ? Uri.decode(namevalue[1]) : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String address = monero.getPath();
|
||||||
|
String paymentId = parms.get(ScannerFragment.QR_PAYMENTID);
|
||||||
|
String amountString = parms.get(ScannerFragment.QR_AMOUNT);
|
||||||
|
long amount = -1;
|
||||||
|
if (amountString != null) {
|
||||||
|
amount = Wallet.getAmountFromString(amountString);
|
||||||
|
}
|
||||||
|
if ((paymentId != null) && !Wallet.isPaymentIdValid(paymentId)) {
|
||||||
|
address = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Helper.isAddressOk(address, WalletManager.getInstance().isTestNet())) {
|
||||||
|
return new BarcodeData(address, paymentId, amount);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BarcodeData getScannedData() {
|
public BarcodeData getScannedData() {
|
||||||
BarcodeData data = scannedData;
|
BarcodeData data = scannedData;
|
||||||
|
@ -640,7 +694,8 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
|
||||||
|
@NonNull int[] grantResults) {
|
||||||
Log.d(TAG, "onRequestPermissionsResult()");
|
Log.d(TAG, "onRequestPermissionsResult()");
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case Helper.PERMISSIONS_REQUEST_CAMERA:
|
case Helper.PERMISSIONS_REQUEST_CAMERA:
|
||||||
|
|
|
@ -34,6 +34,7 @@ import android.widget.TextView;
|
||||||
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
|
import com.m2049r.xmrwallet.layout.TransactionInfoAdapter;
|
||||||
import com.m2049r.xmrwallet.model.TransactionInfo;
|
import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -62,9 +63,9 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
||||||
clProgress = (ConstraintLayout) view.findViewById(R.id.clProgress);
|
clProgress = (ConstraintLayout) view.findViewById(R.id.clProgress);
|
||||||
llUnconfirmedAmount = (LinearLayout) view.findViewById(R.id.llUnconfirmedAmount);
|
llUnconfirmedAmount = (LinearLayout) view.findViewById(R.id.llUnconfirmedAmount);
|
||||||
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
|
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
|
||||||
tvBalance.setText(getDisplayAmount(0));
|
tvBalance.setText(Helper.getDisplayAmount(0));
|
||||||
tvUnconfirmedAmount = (TextView) view.findViewById(R.id.tvUnconfirmedAmount);
|
tvUnconfirmedAmount = (TextView) view.findViewById(R.id.tvUnconfirmedAmount);
|
||||||
tvUnconfirmedAmount.setText(getDisplayAmount(0));
|
tvUnconfirmedAmount.setText(Helper.getDisplayAmount(0));
|
||||||
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);
|
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);
|
||||||
|
|
||||||
bSend = (Button) view.findViewById(R.id.bSend);
|
bSend = (Button) view.findViewById(R.id.bSend);
|
||||||
|
@ -168,23 +169,6 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
||||||
private long firstBlock = 0;
|
private long firstBlock = 0;
|
||||||
private String walletTitle = null;
|
private String walletTitle = null;
|
||||||
|
|
||||||
private String getDisplayAmount(long amount) {
|
|
||||||
String s = Wallet.getDisplayAmount(amount);
|
|
||||||
int lastZero = 0;
|
|
||||||
int decimal = 0;
|
|
||||||
for (int i = s.length() - 1; i >= 0; i--) {
|
|
||||||
if ((lastZero == 0) && (s.charAt(i) != '0')) lastZero = i + 1;
|
|
||||||
// TODO i18n
|
|
||||||
if (s.charAt(i) == '.') {
|
|
||||||
decimal = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Log.d(TAG, decimal + "/" + lastZero + "/" + s);
|
|
||||||
int cutoff = Math.max(lastZero, decimal + 2);
|
|
||||||
return s.substring(0, cutoff);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateStatus(Wallet wallet) {
|
private void updateStatus(Wallet wallet) {
|
||||||
Log.d(TAG, "updateStatus()");
|
Log.d(TAG, "updateStatus()");
|
||||||
if (walletTitle == null) {
|
if (walletTitle == null) {
|
||||||
|
@ -193,8 +177,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
|
||||||
}
|
}
|
||||||
long balance = wallet.getBalance();
|
long balance = wallet.getBalance();
|
||||||
long unlockedBalance = wallet.getUnlockedBalance();
|
long unlockedBalance = wallet.getUnlockedBalance();
|
||||||
tvBalance.setText(getDisplayAmount(unlockedBalance));
|
tvBalance.setText(Helper.getDisplayAmount(unlockedBalance));
|
||||||
tvUnconfirmedAmount.setText(getDisplayAmount(balance - unlockedBalance));
|
tvUnconfirmedAmount.setText(Helper.getDisplayAmount(balance - unlockedBalance));
|
||||||
// balance cannot be less than unlockedBalance
|
// balance cannot be less than unlockedBalance
|
||||||
/*if (balance != unlockedBalance) {
|
/*if (balance != unlockedBalance) {
|
||||||
llPendingAmount.setVisibility(View.VISIBLE);
|
llPendingAmount.setVisibility(View.VISIBLE);
|
||||||
|
|
|
@ -19,10 +19,11 @@ package com.m2049r.xmrwallet.util;
|
||||||
public class BarcodeData {
|
public class BarcodeData {
|
||||||
public String address = null;
|
public String address = null;
|
||||||
public String paymentId = null;
|
public String paymentId = null;
|
||||||
//String amount = null:
|
public long amount = -1;
|
||||||
|
|
||||||
public BarcodeData(String address, String paymentId) {
|
public BarcodeData(String address, String paymentId, long amount) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.paymentId = paymentId;
|
this.paymentId = paymentId;
|
||||||
|
this.amount = amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@ import android.view.WindowManager;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.R;
|
import com.m2049r.xmrwallet.R;
|
||||||
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -135,5 +136,20 @@ public class Helper {
|
||||||
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static public String getDisplayAmount(long amount) {
|
||||||
|
String s = Wallet.getDisplayAmount(amount);
|
||||||
|
int lastZero = 0;
|
||||||
|
int decimal = 0;
|
||||||
|
for (int i = s.length() - 1; i >= 0; i--) {
|
||||||
|
if ((lastZero == 0) && (s.charAt(i) != '0')) lastZero = i + 1;
|
||||||
|
// TODO i18n
|
||||||
|
if (s.charAt(i) == '.') {
|
||||||
|
decimal = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Log.d(TAG, decimal + "/" + lastZero + "/" + s);
|
||||||
|
int cutoff = Math.max(lastZero, decimal + 2);
|
||||||
|
return s.substring(0, cutoff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue