1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-17 02:40:50 +02:00

Compare commits

..

10 Commits

Author SHA1 Message Date
m2049r
e0439a1359 Merge pull request #32 from m2049r/bugfix_scanbutton
fix scan button enable/disable
2017-08-31 18:48:27 +02:00
m2049r
93ec3865da fix scan button enable/disable 2017-08-31 18:43:51 +02:00
m2049r
49e338e80d Merge pull request #31 from m2049r/doc
Update FAQ + version
2017-08-31 18:22:02 +02:00
m2049r
075ddff226 update FAQ + version 2017-08-31 18:19:59 +02:00
m2049r
7eaf17d48e Merge pull request #30 from m2049r/feature_qr_amount
QR scan of amount
2017-08-31 09:58:21 +02:00
m2049r
6822aa83d8 QR scan of amount as well
bugfix: use getSupportFragmentManager everywhere
2017-08-31 09:57:14 +02:00
m2049r
20dbaac4fa Merge pull request #29 from m2049r/bugfix_fragment_v4
use v4 fragment support library to cater for android 5.1
2017-08-31 01:00:52 +02:00
m2049r
726887af2e use v4 fragment support library to cater for android 5.1 2017-08-31 01:00:27 +02:00
m2049r
03da2880ac Merge pull request #28 from m2049r/bugfix_service_timing
make user wait for service to finish
2017-08-30 23:36:01 +02:00
m2049r
78c053f4e8 make user wait for service to finish 2017-08-30 23:35:16 +02:00
16 changed files with 169 additions and 126 deletions

View File

@@ -7,8 +7,8 @@ android {
applicationId "com.m2049r.xmrwallet" applicationId "com.m2049r.xmrwallet"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 25
versionCode 8 versionCode 10
versionName "0.5.1" versionName "0.5.3"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild { externalNativeBuild {
cmake { cmake {

View File

@@ -16,9 +16,9 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;

View File

@@ -16,9 +16,9 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;

View File

@@ -17,9 +17,6 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
@@ -27,6 +24,10 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.Log; import android.util.Log;
@@ -40,6 +41,7 @@ import android.widget.Toast;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.WalletService;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import java.io.File; import java.io.File;
@@ -77,6 +79,10 @@ public class LoginActivity extends AppCompatActivity
@Override @Override
public void onWalletSelected(final String walletName) { public void onWalletSelected(final String walletName) {
if (WalletService.Running) {
Toast.makeText(this, getString(R.string.service_busy), Toast.LENGTH_SHORT).show();
return;
}
Log.d(TAG, "selected wallet is ." + walletName + "."); Log.d(TAG, "selected wallet is ." + walletName + ".");
// now it's getting real, check if wallet exists // now it's getting real, check if wallet exists
String walletPath = Helper.getWalletPath(this, walletName); String walletPath = Helper.getWalletPath(this, walletName);
@@ -276,7 +282,7 @@ public class LoginActivity extends AppCompatActivity
void startLoginFragment() { void startLoginFragment() {
Fragment fragment = new LoginFragment(); Fragment fragment = new LoginFragment();
getFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment).commit(); .add(R.id.fragment_container, fragment).commit();
Log.d(TAG, "LoginFragment added"); Log.d(TAG, "LoginFragment added");
} }
@@ -295,14 +301,14 @@ public class LoginActivity extends AppCompatActivity
if (extras != null) { if (extras != null) {
newFragment.setArguments(extras); newFragment.setArguments(extras);
} }
FragmentTransaction transaction = getFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment); transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(stackName); transaction.addToBackStack(stackName);
transaction.commit(); transaction.commit();
} }
void popFragmentStack(String name) { void popFragmentStack(String name) {
getFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE); getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} }
////////////////////////////////////////// //////////////////////////////////////////
@@ -312,7 +318,7 @@ public class LoginActivity extends AppCompatActivity
public void createWallet(final String name, final String password, final WalletCreator walletCreator) { public void createWallet(final String name, final String password, final WalletCreator walletCreator) {
final GenerateFragment genFragment = (GenerateFragment) final GenerateFragment genFragment = (GenerateFragment)
getFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
File newWalletFolder = new File(getStorageRoot(), ".new"); File newWalletFolder = new File(getStorageRoot(), ".new");
if (!newWalletFolder.exists()) { if (!newWalletFolder.exists()) {
if (!newWalletFolder.mkdir()) { if (!newWalletFolder.mkdir()) {

View File

@@ -16,12 +16,12 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.os.StrictMode; import android.os.StrictMode;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.Log; import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.KeyEvent; import android.view.KeyEvent;

View File

@@ -16,10 +16,10 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -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

@@ -16,11 +16,11 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
@@ -51,7 +51,7 @@ public class SendFragment extends Fragment {
EditText etAddress; EditText etAddress;
EditText etPaymentId; EditText etPaymentId;
EditText etAmount; EditText etAmount;
Button bAddress; Button bScan;
Button bSweep; Button bSweep;
Spinner sMixin; Spinner sMixin;
Spinner sPriority; Spinner sPriority;
@@ -84,7 +84,7 @@ public class SendFragment extends Fragment {
etAddress = (EditText) view.findViewById(R.id.etAddress); etAddress = (EditText) view.findViewById(R.id.etAddress);
etPaymentId = (EditText) view.findViewById(R.id.etPaymentId); etPaymentId = (EditText) view.findViewById(R.id.etPaymentId);
etAmount = (EditText) view.findViewById(R.id.etAmount); etAmount = (EditText) view.findViewById(R.id.etAmount);
bAddress = (Button) view.findViewById(R.id.bAddress); bScan = (Button) view.findViewById(R.id.bScan);
bSweep = (Button) view.findViewById(R.id.bSweep); bSweep = (Button) view.findViewById(R.id.bSweep);
bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend); bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend);
bPaymentId = (Button) view.findViewById(R.id.bPaymentId); bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
@@ -199,7 +199,7 @@ public class SendFragment extends Fragment {
} }
}); });
bAddress.setOnClickListener(new View.OnClickListener() { bScan.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
activityCallback.onScanAddress(); activityCallback.onScanAddress();
@@ -321,6 +321,7 @@ public class SendFragment extends Fragment {
etAddress.setEnabled(false); etAddress.setEnabled(false);
etPaymentId.setEnabled(false); etPaymentId.setEnabled(false);
etAmount.setEnabled(false); etAmount.setEnabled(false);
bScan.setEnabled(false);
bPaymentId.setEnabled(false); bPaymentId.setEnabled(false);
bSweep.setEnabled(false); bSweep.setEnabled(false);
bPrepareSend.setEnabled(false); bPrepareSend.setEnabled(false);
@@ -332,6 +333,7 @@ public class SendFragment extends Fragment {
etAddress.setEnabled(true); etAddress.setEnabled(true);
etPaymentId.setEnabled(true); etPaymentId.setEnabled(true);
etAmount.setEnabled(true); etAmount.setEnabled(true);
bScan.setEnabled(true);
bPaymentId.setEnabled(true); bPaymentId.setEnabled(true);
bSweep.setEnabled(true); bSweep.setEnabled(true);
bPrepareSend.setEnabled(true); bPrepareSend.setEnabled(true);
@@ -373,26 +375,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

@@ -16,28 +16,23 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.InputType; import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.m2049r.xmrwallet.model.TransactionInfo; import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Transfer; import com.m2049r.xmrwallet.model.Transfer;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;

View File

@@ -16,18 +16,20 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; 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;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.Log; import android.util.Log;
@@ -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,
@@ -155,7 +160,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
} }
Fragment walletFragment = new WalletFragment(); Fragment walletFragment = new WalletFragment();
getFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, walletFragment).commit(); .add(R.id.fragment_container, walletFragment).commit();
Log.d(TAG, "fragment added"); Log.d(TAG, "fragment added");
@@ -336,7 +341,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
Log.d(TAG, "onRefreshed()"); Log.d(TAG, "onRefreshed()");
try { try {
final WalletFragment walletFragment = (WalletFragment) final WalletFragment walletFragment = (WalletFragment)
getFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (wallet.isSynchronized()) { if (wallet.isSynchronized()) {
Log.d(TAG, "onRefreshed() synced"); Log.d(TAG, "onRefreshed() synced");
releaseWakeLock(); // the idea is to stay awake until synced releaseWakeLock(); // the idea is to stay awake until synced
@@ -401,7 +406,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
public void onCreatedTransaction(final PendingTransaction pendingTransaction) { public void onCreatedTransaction(final PendingTransaction pendingTransaction) {
try { try {
final SendFragment sendFragment = (SendFragment) final SendFragment sendFragment = (SendFragment)
getFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
PendingTransaction.Status status = pendingTransaction.getStatus(); PendingTransaction.Status status = pendingTransaction.getStatus();
@@ -440,7 +445,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
public void onSetNotes(final boolean success) { public void onSetNotes(final boolean success) {
try { try {
final TxFragment txFragment = (TxFragment) final TxFragment txFragment = (TxFragment)
getFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
if (!success) { if (!success) {
@@ -460,7 +465,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
public void onProgress(final String text) { public void onProgress(final String text) {
try { try {
final WalletFragment walletFragment = (WalletFragment) final WalletFragment walletFragment = (WalletFragment)
getFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
walletFragment.onProgress(text); walletFragment.onProgress(text);
@@ -477,7 +482,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
public void onProgress(final int n) { public void onProgress(final int n) {
try { try {
final WalletFragment walletFragment = (WalletFragment) final WalletFragment walletFragment = (WalletFragment)
getFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
walletFragment.onProgress(n); walletFragment.onProgress(n);
@@ -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);
} }
} }
@@ -583,14 +588,14 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
if (extras != null) { if (extras != null) {
newFragment.setArguments(extras); newFragment.setArguments(extras);
} }
FragmentTransaction transaction = getFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment); transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(stackName); transaction.addToBackStack(stackName);
transaction.commit(); transaction.commit();
} }
private void onWalletDetails() { private void onWalletDetails() {
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container); Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (!(fragment instanceof GenerateReviewFragment)) { if (!(fragment instanceof GenerateReviewFragment)) {
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString("type", GenerateReviewFragment.VIEW_WALLET); extras.putString("type", GenerateReviewFragment.VIEW_WALLET);
@@ -605,7 +610,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
private void startScanFragment() { private void startScanFragment() {
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container); Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (fragment instanceof SendFragment) { if (fragment instanceof SendFragment) {
Bundle extras = new Bundle(); Bundle extras = new Bundle();
replaceFragment(new ScannerFragment(), null, extras); replaceFragment(new ScannerFragment(), null, extras);
@@ -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

@@ -16,21 +16,16 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.support.constraint.ConstraintLayout; import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AlertDialog; import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.Button; import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
@@ -38,9 +33,8 @@ 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.Transfer;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.util.Helper;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.List; import java.util.List;
@@ -69,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);
@@ -175,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) {
@@ -200,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,7 @@ package com.m2049r.xmrwallet.service;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -30,13 +27,11 @@ import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.Process; import android.os.Process;
import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.WalletActivity; import com.m2049r.xmrwallet.WalletActivity;
import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.model.PendingTransaction;
import com.m2049r.xmrwallet.model.TransactionHistory;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletListener; import com.m2049r.xmrwallet.model.WalletListener;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
@@ -44,6 +39,8 @@ import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.TxData; import com.m2049r.xmrwallet.util.TxData;
public class WalletService extends Service { public class WalletService extends Service {
public static boolean Running = false;
final static String TAG = "WalletService"; final static String TAG = "WalletService";
final static int NOTIFICATION_ID = 2049; final static int NOTIFICATION_ID = 2049;
@@ -400,9 +397,6 @@ public class WalletService extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
//mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//showNotification();
// We are using a HandlerThread and a Looper to avoid loading and closing // We are using a HandlerThread and a Looper to avoid loading and closing
// concurrency // concurrency
MoneroHandlerThread thread = new MoneroHandlerThread("WalletService", MoneroHandlerThread thread = new MoneroHandlerThread("WalletService",
@@ -419,8 +413,6 @@ public class WalletService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
Log.d(TAG, "onDestroy()"); Log.d(TAG, "onDestroy()");
// Cancel the persistent notification.
//mNM.cancel(NOTIFICATION);
if (this.listener != null) { if (this.listener != null) {
Log.w(TAG, "onDestroy() with active listener"); Log.w(TAG, "onDestroy() with active listener");
// no need to stop() here because the wallet closing should have been triggered // no need to stop() here because the wallet closing should have been triggered
@@ -438,7 +430,8 @@ public class WalletService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
// when the activity satrts the service, it expects to start it for a new wallet Running = true;
// when the activity starts the service, it expects to start it for a new wallet
// the service is possibly still occupied with saving the last opened wallet // the service is possibly still occupied with saving the last opened wallet
// so we queue the open request // so we queue the open request
// this should not matter since the old activity is not getting updates // this should not matter since the old activity is not getting updates
@@ -514,6 +507,7 @@ public class WalletService extends Service {
} }
stopForeground(true); stopForeground(true);
stopSelf(); stopSelf();
Running = false;
} }
private Wallet loadWallet(String walletName, String walletPassword) { private Wallet loadWallet(String walletName, String walletPassword) {

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

View File

@@ -52,7 +52,7 @@
android:textSize="16sp" /> android:textSize="16sp" />
<Button <Button
android:id="@+id/bAddress" android:id="@+id/bScan"
android:layout_width="0sp" android:layout_width="0sp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"

View File

@@ -22,6 +22,8 @@
<string name="status_transaction_failed">Transaction failed!</string> <string name="status_transaction_failed">Transaction failed!</string>
<string name="status_transaction_prepare_failed">Could not create transaction!</string> <string name="status_transaction_prepare_failed">Could not create transaction!</string>
<string name="service_busy">I am still busy with your last wallet &#8230;</string>
<string name="prompt_password">Password for</string> <string name="prompt_password">Password for</string>
<string name="bad_password">Bad password!</string> <string name="bad_password">Bad password!</string>
<string name="bad_wallet">Wallet does not exists!</string> <string name="bad_wallet">Wallet does not exists!</string>

View File

@@ -2,6 +2,7 @@
## What features does it have? ## What features does it have?
- Support for Android >= 5.0 with ARM processor
- Testnet and Mainnet - Testnet and Mainnet
- Generate new wallets - Generate new wallets
- Recover wallets form mnemonic seed or from keys - Recover wallets form mnemonic seed or from keys
@@ -15,8 +16,7 @@
- Access to daemon with username/password and nonstandard port - Access to daemon with username/password and nonstandard port
- Only 5 decimal places shown in transactions (full amount in details - click on transaction) - Only 5 decimal places shown in transactions (full amount in details - click on transaction)
- All significant figures shown in balance - All significant figures shown in balance
- QR Code scanning incl. payment ID - make sure to *ALWAYS* verify - QR Code scanning - make sure to *ALWAYS* verify the scanned code is what it is advertised to be!
the scanned code is what it is advertised to be!
## I cannot select and copy the mnemonic seed ## I cannot select and copy the mnemonic seed
Copying anything to the clipboard on Android exposes it to any other App running. So this Copying anything to the clipboard on Android exposes it to any other App running. So this