QR scan of amount as well

bugfix: use getSupportFragmentManager everywhere
This commit is contained in:
m2049r 2017-08-31 09:04:32 +02:00
parent 20dbaac4fa
commit 6822aa83d8
7 changed files with 121 additions and 70 deletions

View File

@ -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);
} }
////////////////////////////////////////// //////////////////////////////////////////

View File

@ -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 {

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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;
} }
} }

View File

@ -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);
}
} }