mirror of https://github.com/m2049r/xmrwallet.git
QR Scanning incl. payment id
This commit is contained in:
parent
2d42a0287d
commit
f5535dbefa
|
@ -0,0 +1,10 @@
|
||||||
|
<component name="libraryTable">
|
||||||
|
<library name="core-1.9.8">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/jars/classes.jar!/" />
|
||||||
|
<root url="file://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/res" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<component name="libraryTable">
|
||||||
|
<library name="core-3.3.0">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/73c49077166faa4c3c0059c5f583d1d7bd1475fe/core-3.3.0.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/39d966e052e28fc7d83793b02e0af97ccf955745/core-3.3.0-sources.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</component>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<component name="libraryTable">
|
||||||
|
<library name="zxing-1.9.8">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/jars/classes.jar!/" />
|
||||||
|
<root url="file://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/res" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
|
@ -46,5 +46,6 @@ dependencies {
|
||||||
compile 'com.android.support:support-v4:25.3.1'
|
compile 'com.android.support:support-v4:25.3.1'
|
||||||
compile 'com.android.support:recyclerview-v7:25.3.1'
|
compile 'com.android.support:recyclerview-v7:25.3.1'
|
||||||
compile 'com.android.support:cardview-v7:25.3.1'
|
compile 'com.android.support:cardview-v7:25.3.1'
|
||||||
|
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 dm77, m2049r
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.m2049r.xmrwallet;
|
||||||
|
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.Result;
|
||||||
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
|
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||||
|
|
||||||
|
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
||||||
|
static final String TAG = "ScannerFragment";
|
||||||
|
|
||||||
|
Listener activityCallback;
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
void onAddressScanned(String address, String paymentId);
|
||||||
|
|
||||||
|
boolean isPaymentIdValid(String paymentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ZXingScannerView mScannerView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
Log.d(TAG, "onCreateView");
|
||||||
|
mScannerView = new ZXingScannerView(getActivity());
|
||||||
|
return mScannerView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Log.d(TAG, "onResume");
|
||||||
|
mScannerView.setResultHandler(this);
|
||||||
|
mScannerView.startCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final String URI_PREFIX = "monero:";
|
||||||
|
static final String PAYMENTID_STRING = "?tx_payment_id=";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleResult(Result rawResult) {
|
||||||
|
Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
|
||||||
|
String text = rawResult.getText();
|
||||||
|
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
||||||
|
(text.startsWith(URI_PREFIX))) {
|
||||||
|
String address = null;
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.send_qr_invalid), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note from dm77:
|
||||||
|
// * Wait 2 seconds to resume the preview.
|
||||||
|
// * On older devices continuously stopping and resuming camera preview can result in freezing the app.
|
||||||
|
// * I don't know why this is the case but I don't have the time to figure out.
|
||||||
|
Handler handler = new Handler();
|
||||||
|
handler.postDelayed(new
|
||||||
|
|
||||||
|
Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mScannerView.resumeCameraPreview(ScannerFragment.this);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
Log.d(TAG, "onPause");
|
||||||
|
mScannerView.stopCamera();
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
Log.d(TAG, "attaching scan");
|
||||||
|
if (context instanceof Listener) {
|
||||||
|
this.activityCallback = (Listener) context;
|
||||||
|
} else {
|
||||||
|
throw new ClassCastException(context.toString()
|
||||||
|
+ " must implement Listener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,10 +20,12 @@ 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.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;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -40,14 +42,16 @@ import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
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.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||||
import com.m2049r.xmrwallet.util.TxData;
|
import com.m2049r.xmrwallet.util.TxData;
|
||||||
|
|
||||||
public class SendFragment extends Fragment {
|
public class SendFragment extends Fragment {
|
||||||
static final String TAG = "GenerateFragment";
|
static final String TAG = "SendFragment";
|
||||||
|
|
||||||
EditText etAddress;
|
EditText etAddress;
|
||||||
EditText etPaymentId;
|
EditText etPaymentId;
|
||||||
EditText etAmount;
|
EditText etAmount;
|
||||||
|
Button bAddress;
|
||||||
Button bSweep;
|
Button bSweep;
|
||||||
Spinner sMixin;
|
Spinner sMixin;
|
||||||
Spinner sPriority;
|
Spinner sPriority;
|
||||||
|
@ -80,6 +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);
|
||||||
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);
|
||||||
|
@ -194,6 +199,13 @@ public class SendFragment extends Fragment {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bAddress.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
activityCallback.onScanAddress();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
@ -231,7 +243,14 @@ public class SendFragment extends Fragment {
|
||||||
if (testnet) {
|
if (testnet) {
|
||||||
send();
|
send();
|
||||||
} else {
|
} else {
|
||||||
bReallySend.setVisibility(View.VISIBLE);
|
etNotes.setEnabled(false);
|
||||||
|
Handler handler = new Handler();
|
||||||
|
handler.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
bReallySend.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -256,11 +275,7 @@ public class SendFragment extends Fragment {
|
||||||
|
|
||||||
private boolean addressOk() {
|
private boolean addressOk() {
|
||||||
String address = etAddress.getText().toString();
|
String address = etAddress.getText().toString();
|
||||||
if (WalletManager.getInstance().isTestNet()) {
|
return Helper.isAddressOk(address, WalletManager.getInstance().isTestNet());
|
||||||
return ((address.length() == 95) && ("9A".indexOf(address.charAt(0)) >= 0));
|
|
||||||
} else {
|
|
||||||
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean amountOk() {
|
private boolean amountOk() {
|
||||||
|
@ -321,6 +336,8 @@ public class SendFragment extends Fragment {
|
||||||
bSweep.setEnabled(true);
|
bSweep.setEnabled(true);
|
||||||
bPrepareSend.setEnabled(true);
|
bPrepareSend.setEnabled(true);
|
||||||
llConfirmSend.setVisibility(View.GONE);
|
llConfirmSend.setVisibility(View.GONE);
|
||||||
|
bSend.setEnabled(true);
|
||||||
|
etNotes.setEnabled(true);
|
||||||
bReallySend.setVisibility(View.GONE);
|
bReallySend.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,6 +364,35 @@ public class SendFragment extends Fragment {
|
||||||
|
|
||||||
void onDisposeRequest();
|
void onDisposeRequest();
|
||||||
|
|
||||||
|
void onScanAddress();
|
||||||
|
|
||||||
|
BarcodeData getScannedData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
BarcodeData data = activityCallback.getScannedData();
|
||||||
|
if (data != null) {
|
||||||
|
String scannedAddress = data.address;
|
||||||
|
if (scannedAddress != null) {
|
||||||
|
etAddress.setText(scannedAddress);
|
||||||
|
}
|
||||||
|
String scannedPaymenId = data.paymentId;
|
||||||
|
if (scannedPaymenId != null) {
|
||||||
|
etPaymentId.setText(scannedPaymenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
|
|
@ -23,9 +23,11 @@ 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.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.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;
|
||||||
|
@ -39,10 +41,14 @@ import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||||
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.service.WalletService;
|
||||||
|
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.TxData;
|
import com.m2049r.xmrwallet.util.TxData;
|
||||||
|
|
||||||
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
|
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
|
||||||
WalletService.Observer, SendFragment.Listener, TxFragment.Listener, GenerateReviewFragment.ListenerWithWallet {
|
WalletService.Observer, SendFragment.Listener, TxFragment.Listener,
|
||||||
|
GenerateReviewFragment.ListenerWithWallet,
|
||||||
|
ScannerFragment.Listener {
|
||||||
private static final String TAG = "WalletActivity";
|
private static final String TAG = "WalletActivity";
|
||||||
|
|
||||||
public static final String REQUEST_ID = "id";
|
public static final String REQUEST_ID = "id";
|
||||||
|
@ -596,4 +602,60 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||||
public void onDisposeRequest() {
|
public void onDisposeRequest() {
|
||||||
getWallet().disposePendingTransaction();
|
getWallet().disposePendingTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void startScanFragment() {
|
||||||
|
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
|
if (fragment instanceof SendFragment) {
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
replaceFragment(new ScannerFragment(), null, extras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// QR scanner callbacks
|
||||||
|
@Override
|
||||||
|
public void onScanAddress() {
|
||||||
|
if (Helper.getCameraPermission(this)) {
|
||||||
|
startScanFragment();
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "Waiting for permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private BarcodeData scannedData = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAddressScanned(String address, String paymentId) {
|
||||||
|
// Log.d(TAG, "got " + address);
|
||||||
|
scannedData = new BarcodeData(address, paymentId);
|
||||||
|
popFragmentStack(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BarcodeData getScannedData() {
|
||||||
|
BarcodeData data = scannedData;
|
||||||
|
scannedData = null;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||||
|
Log.d(TAG, "onRequestPermissionsResult()");
|
||||||
|
switch (requestCode) {
|
||||||
|
case Helper.PERMISSIONS_REQUEST_CAMERA:
|
||||||
|
// If request is cancelled, the result arrays are empty.
|
||||||
|
if (grantResults.length > 0
|
||||||
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
startScanFragment();
|
||||||
|
} else {
|
||||||
|
String msg = getString(R.string.message_camera_not_permitted);
|
||||||
|
Log.e(TAG, msg);
|
||||||
|
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -127,6 +127,7 @@ public class WalletService extends Service {
|
||||||
boolean fullRefresh = false;
|
boolean fullRefresh = false;
|
||||||
updateDaemonState(wallet, wallet.isSynchronized() ? height : 0);
|
updateDaemonState(wallet, wallet.isSynchronized() ? height : 0);
|
||||||
if (!wallet.isSynchronized()) {
|
if (!wallet.isSynchronized()) {
|
||||||
|
updated = true;
|
||||||
// we want to see our transactions as they come in
|
// we want to see our transactions as they come in
|
||||||
wallet.getHistory().refresh();
|
wallet.getHistory().refresh();
|
||||||
int txCount = wallet.getHistory().getCount();
|
int txCount = wallet.getHistory().getCount();
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 m2049r
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.m2049r.xmrwallet.util;
|
||||||
|
|
||||||
|
public class BarcodeData {
|
||||||
|
public String address = null;
|
||||||
|
public String paymentId = null;
|
||||||
|
//String amount = null:
|
||||||
|
|
||||||
|
public BarcodeData(String address, String paymentId) {
|
||||||
|
this.address = address;
|
||||||
|
this.paymentId = paymentId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.WalletManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -71,6 +72,24 @@ public class Helper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final int PERMISSIONS_REQUEST_CAMERA = 1;
|
||||||
|
|
||||||
|
static public boolean getCameraPermission(Activity context) {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||||
|
if (context.checkSelfPermission(Manifest.permission.CAMERA)
|
||||||
|
== PackageManager.PERMISSION_DENIED) {
|
||||||
|
Log.d(TAG, "Permission denied for CAMERA - requesting it");
|
||||||
|
String[] permissions = {Manifest.permission.CAMERA};
|
||||||
|
context.requestPermissions(permissions, PERMISSIONS_REQUEST_CAMERA);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static public String getWalletPath(Context context, String aWalletName) {
|
static public String getWalletPath(Context context, String aWalletName) {
|
||||||
File walletDir = getStorageRoot(context);
|
File walletDir = getStorageRoot(context);
|
||||||
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
||||||
|
@ -107,4 +126,14 @@ public class Helper {
|
||||||
static public void hideKeyboardAlways(Activity act) {
|
static public void hideKeyboardAlways(Activity act) {
|
||||||
act.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
act.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public boolean isAddressOk(String address, boolean testnet) {
|
||||||
|
if (address == null) return false;
|
||||||
|
if (testnet) {
|
||||||
|
return ((address.length() == 95) && ("9A".indexOf(address.charAt(0)) >= 0));
|
||||||
|
} else {
|
||||||
|
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/sMixin"
|
android:id="@+id/sMixin"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:entries="@array/mixin"
|
android:entries="@array/mixin"
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/sPriority"
|
android:id="@+id/sPriority"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:entries="@array/priority"
|
android:entries="@array/priority"
|
||||||
|
@ -32,25 +32,49 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/etAddress"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/send_address_hint"
|
android:orientation="horizontal"
|
||||||
android:imeOptions="actionNext"
|
android:layout_marginBottom="4sp"
|
||||||
android:inputType="textMultiLine"
|
android:layout_marginTop="4sp"
|
||||||
android:textAlignment="center"
|
android:weightSum="10">
|
||||||
android:textSize="16sp" />
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etAddress"
|
||||||
|
android:layout_width="0sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="8"
|
||||||
|
android:hint="@string/send_address_hint"
|
||||||
|
android:imeOptions="actionNext"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/bAddress"
|
||||||
|
android:layout_width="0sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:minHeight="36sp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
android:enabled="true"
|
||||||
|
android:text="@string/send_qr_hint"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginBottom="4sp"
|
||||||
|
android:layout_marginTop="4sp"
|
||||||
android:weightSum="10">
|
android:weightSum="10">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etPaymentId"
|
android:id="@+id/etPaymentId"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="8"
|
android:layout_weight="8"
|
||||||
android:hint="@string/send_paymentid_hint"
|
android:hint="@string/send_paymentid_hint"
|
||||||
|
@ -61,10 +85,10 @@
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/bPaymentId"
|
android:id="@+id/bPaymentId"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_gravity="center"
|
||||||
android:layout_marginTop="8dp"
|
android:minHeight="36sp"
|
||||||
android:layout_weight="2"
|
android:layout_weight="2"
|
||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
@ -76,11 +100,13 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginBottom="4sp"
|
||||||
|
android:layout_marginTop="4sp"
|
||||||
android:weightSum="10">
|
android:weightSum="10">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etAmount"
|
android:id="@+id/etAmount"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="8"
|
android:layout_weight="8"
|
||||||
android:hint="@string/send_amount_hint"
|
android:hint="@string/send_amount_hint"
|
||||||
|
@ -91,10 +117,8 @@
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/bSweep"
|
android:id="@+id/bSweep"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_weight="2"
|
android:layout_weight="2"
|
||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
@ -106,8 +130,9 @@
|
||||||
android:id="@+id/bPrepareSend"
|
android:id="@+id/bPrepareSend"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="4sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="4sp"
|
||||||
|
android:minHeight="36sp"
|
||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
android:text="@string/send_prepare_hint" />
|
android:text="@string/send_prepare_hint" />
|
||||||
|
@ -124,18 +149,19 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:layout_marginBottom="4sp"
|
||||||
|
android:layout_marginTop="4sp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/bDispose"
|
android:id="@+id/bDispose"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:minHeight="36sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginBottom="4sp"
|
||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:text="@string/send_dispose_hint" />
|
android:text="@string/send_dispose_hint" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -144,9 +170,9 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTxAmountLabel"
|
android:id="@+id/tvTxAmountLabel"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8sp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/send_amount_label"
|
android:text="@string/send_amount_label"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
|
@ -155,9 +181,9 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTxAmount"
|
android:id="@+id/tvTxAmount"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8sp"
|
||||||
android:layout_weight="2"
|
android:layout_weight="2"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
@ -171,9 +197,9 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTxFeeLabel"
|
android:id="@+id/tvTxFeeLabel"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="4sp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/send_fee_label"
|
android:text="@string/send_fee_label"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
|
@ -182,9 +208,9 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTxFee"
|
android:id="@+id/tvTxFee"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8sp"
|
||||||
android:layout_weight="2"
|
android:layout_weight="2"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
@ -198,9 +224,9 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTxDustLabel"
|
android:id="@+id/tvTxDustLabel"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8sp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/send_dust_label"
|
android:text="@string/send_dust_label"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
|
@ -209,9 +235,9 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTxDust"
|
android:id="@+id/tvTxDust"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8sp"
|
||||||
android:layout_weight="2"
|
android:layout_weight="2"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
@ -221,7 +247,7 @@
|
||||||
android:id="@+id/etNotes"
|
android:id="@+id/etNotes"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="4sp"
|
||||||
android:hint="@string/send_notes_hint"
|
android:hint="@string/send_notes_hint"
|
||||||
android:imeOptions="actionDone"
|
android:imeOptions="actionDone"
|
||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
|
@ -232,8 +258,9 @@
|
||||||
android:id="@+id/bSend"
|
android:id="@+id/bSend"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="4sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="4sp"
|
||||||
|
android:minHeight="36sp"
|
||||||
android:background="@color/colorPrimary"
|
android:background="@color/colorPrimary"
|
||||||
android:text="@string/send_send_hint" />
|
android:text="@string/send_send_hint" />
|
||||||
|
|
||||||
|
@ -241,8 +268,8 @@
|
||||||
android:id="@+id/bReallySend"
|
android:id="@+id/bReallySend"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="4sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="4sp"
|
||||||
android:background="@color/moneroOrange"
|
android:background="@color/moneroOrange"
|
||||||
android:text="@string/send_really_send_hint"
|
android:text="@string/send_really_send_hint"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<string name="menu_info">Details</string>
|
<string name="menu_info">Details</string>
|
||||||
|
|
||||||
<string name="prompt_daemon">[<user>:<pass>@]<daemonhost>[:<port>]</string>
|
<string name="prompt_daemon">[<user>:<pass>@]<daemon>[:<port>]</string>
|
||||||
<string name="prompt_mainnet">Net Selection</string>
|
<string name="prompt_mainnet">Net Selection</string>
|
||||||
<string name="connect_testnet">TestNet</string>
|
<string name="connect_testnet">TestNet</string>
|
||||||
<string name="connect_mainnet">MainNet</string>
|
<string name="connect_mainnet">MainNet</string>
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
<string name="prompt_problems">Problems</string>
|
<string name="prompt_problems">Problems</string>
|
||||||
<string name="message_strorage_not_writable">External Storage is not writable! Panic!</string>
|
<string name="message_strorage_not_writable">External Storage is not writable! Panic!</string>
|
||||||
<string name="message_strorage_not_permitted">We really need those External Storage permissions!</string>
|
<string name="message_strorage_not_permitted">We really need those External Storage permissions!</string>
|
||||||
|
<string name="message_camera_not_permitted">No camera = No QR scanning!</string>
|
||||||
|
|
||||||
<string name="generate_title">Create Wallet</string>
|
<string name="generate_title">Create Wallet</string>
|
||||||
<string name="generate_name_hint">Wallet Name</string>
|
<string name="generate_name_hint">Wallet Name</string>
|
||||||
|
@ -111,11 +112,13 @@
|
||||||
<string name="send_mixin_hint">Mixin</string>
|
<string name="send_mixin_hint">Mixin</string>
|
||||||
<string name="send_sweep_hint">Sweep</string>
|
<string name="send_sweep_hint">Sweep</string>
|
||||||
<string name="send_generate_paymentid_hint">Generate</string>
|
<string name="send_generate_paymentid_hint">Generate</string>
|
||||||
|
<string name="send_qr_hint">Scan</string>
|
||||||
<string name="send_prepare_hint">Prepare</string>
|
<string name="send_prepare_hint">Prepare</string>
|
||||||
<string name="send_dispose_hint">Dispose (Undo)</string>
|
<string name="send_dispose_hint">Dispose (Undo)</string>
|
||||||
<string name="send_send_hint">Spend my sweet Moneroj</string>
|
<string name="send_send_hint">Spend my sweet Moneroj</string>
|
||||||
<string name="send_really_send_hint">I understand I am on mainnet\nTHis is real Monero!</string>
|
<string name="send_really_send_hint">I understand I am sending real Monero!</string>
|
||||||
|
<string name="send_qr_invalid">Not a monero QR Code</string>
|
||||||
|
<string name="send_qr_address_invalid">Invalid Monero address</string>
|
||||||
<string name="send_preparing_progress">Preparing transaction</string>
|
<string name="send_preparing_progress">Preparing transaction</string>
|
||||||
|
|
||||||
<string name="send_amount_label">Amount</string>
|
<string name="send_amount_label">Amount</string>
|
||||||
|
|
Loading…
Reference in New Issue