mirror of
https://github.com/wownero/wownerujo.git
synced 2026-10-22 09:48:33 +02:00
Receive QR code
This commit is contained in:
@@ -69,12 +69,9 @@ public class GenerateFragment extends Fragment {
|
||||
bGenerate = (Button) view.findViewById(R.id.bGenerate);
|
||||
|
||||
etWalletMnemonic.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
etWalletAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
etWalletViewKey.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
etWalletSpendKey.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
|
||||
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||
//etWalletMnemonic.setTextIsSelectable(testnet);
|
||||
etWalletAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
etWalletViewKey.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
etWalletSpendKey.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
|
||||
Helper.showKeyboard(getActivity());
|
||||
etWalletName.addTextChangedListener(new TextWatcher() {
|
||||
@@ -298,8 +295,8 @@ public class GenerateFragment extends Fragment {
|
||||
private void generateWallet() {
|
||||
String name = etWalletName.getText().toString();
|
||||
if (name.length() == 0) return;
|
||||
String walletPath = Helper.getWalletPath(getActivity(), name);
|
||||
if (WalletManager.getInstance().walletExists(walletPath)) {
|
||||
File walletFile = Helper.getWalletFile(getActivity(), name);
|
||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||
Toast.makeText(getActivity(), getString(R.string.generate_wallet_exists), Toast.LENGTH_LONG).show();
|
||||
etWalletName.requestFocus();
|
||||
return;
|
||||
|
||||
@@ -79,10 +79,10 @@ public class GenerateReviewFragment extends Fragment {
|
||||
Bundle b = getArguments();
|
||||
String type = b.getString("type");
|
||||
if (!type.equals(VIEW_WALLET)) {
|
||||
String name = b.getString("name");
|
||||
String path = b.getString("path");
|
||||
String password = b.getString("password");
|
||||
tvWalletName.setText(new File(name).getName());
|
||||
show(name, password, type);
|
||||
tvWalletName.setText(new File(path).getName());
|
||||
show(path, password, type);
|
||||
} else {
|
||||
show(walletCallback.getWallet(), null, type);
|
||||
}
|
||||
|
||||
@@ -85,8 +85,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
}
|
||||
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
||||
// now it's getting real, check if wallet exists
|
||||
String walletPath = Helper.getWalletPath(this, walletName);
|
||||
if (WalletManager.getInstance().walletExists(walletPath)) {
|
||||
File walletFile = Helper.getWalletFile(this, walletName);
|
||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||
promptPassword(walletName, new PasswordAction() {
|
||||
@Override
|
||||
public void action(String walletName, String password) {
|
||||
@@ -101,12 +101,12 @@ public class LoginActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onWalletDetails(final String walletName) {
|
||||
Log.d(TAG, "details for wallet ." + walletName + ".");
|
||||
final String walletPath = Helper.getWalletPath(this, walletName);
|
||||
if (WalletManager.getInstance().walletExists(walletPath)) {
|
||||
final File walletFile = Helper.getWalletFile(this, walletName);
|
||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||
promptPassword(walletName, new PasswordAction() {
|
||||
@Override
|
||||
public void action(String walletName, String password) {
|
||||
startDetails(walletPath, password, GenerateReviewFragment.VIEW_DETAILS);
|
||||
startDetails(walletFile, password, GenerateReviewFragment.VIEW_DETAILS);
|
||||
}
|
||||
});
|
||||
} else { // this cannot really happen as we prefilter choices
|
||||
@@ -114,6 +114,18 @@ public class LoginActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalletReceive(final String walletName) {
|
||||
Log.d(TAG, "receive for wallet ." + walletName + ".");
|
||||
final File walletFile = Helper.getWalletFile(this, walletName);
|
||||
if (WalletManager.getInstance().walletExists(walletFile)) {
|
||||
String address = WalletManager.getInstance().getWalletInfo(walletFile).address;
|
||||
startReceive(address);
|
||||
} else { // this cannot really happen as we prefilter choices
|
||||
Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddWallet() {
|
||||
startGenerateFragment();
|
||||
@@ -251,15 +263,22 @@ public class LoginActivity extends AppCompatActivity
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
void startDetails(final String walletPath, final String password, String type) {
|
||||
void startDetails(final File walletFile, final String password, String type) {
|
||||
Log.d(TAG, "startDetails()");
|
||||
Bundle b = new Bundle();
|
||||
b.putString("name", walletPath);
|
||||
b.putString("path", walletFile.getAbsolutePath());
|
||||
b.putString("password", password);
|
||||
b.putString("type", type);
|
||||
startReviewFragment(b);
|
||||
}
|
||||
|
||||
void startReceive(String address) {
|
||||
Log.d(TAG, "startReceive()");
|
||||
Bundle b = new Bundle();
|
||||
b.putString("address", address);
|
||||
startReceiveFragment(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||
Log.d(TAG, "onRequestPermissionsResult()");
|
||||
@@ -297,6 +316,11 @@ public class LoginActivity extends AppCompatActivity
|
||||
Log.d(TAG, "GenerateReviewFragment placed");
|
||||
}
|
||||
|
||||
void startReceiveFragment(Bundle extras) {
|
||||
replaceFragment(new ReceiveFragment(), null, extras);
|
||||
Log.d(TAG, "ReceiveFragment placed");
|
||||
}
|
||||
|
||||
void replaceFragment(Fragment newFragment, String stackName, Bundle extras) {
|
||||
if (extras != null) {
|
||||
newFragment.setArguments(extras);
|
||||
@@ -345,29 +369,29 @@ public class LoginActivity extends AppCompatActivity
|
||||
return;
|
||||
}
|
||||
|
||||
String newWalletPath = new File(newWalletFolder, name).getAbsolutePath();
|
||||
boolean success = walletCreator.createWallet(newWalletPath, password);
|
||||
File newWalletFile = new File(newWalletFolder, name);
|
||||
boolean success = walletCreator.createWallet(newWalletFile, password);
|
||||
if (success) {
|
||||
startDetails(newWalletPath, password, GenerateReviewFragment.VIEW_ACCEPT);
|
||||
startDetails(newWalletFile, password, GenerateReviewFragment.VIEW_ACCEPT);
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.generate_wallet_create_failed), Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "Could not create new wallet in " + newWalletPath);
|
||||
Log.e(TAG, "Could not create new wallet in " + newWalletFile.getAbsolutePath());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
interface WalletCreator {
|
||||
boolean createWallet(String path, String password);
|
||||
boolean createWallet(File aFile, String password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenerate(String name, String password) {
|
||||
createWallet(name, password,
|
||||
new WalletCreator() {
|
||||
public boolean createWallet(String path, String password) {
|
||||
public boolean createWallet(File aFile, String password) {
|
||||
Wallet newWallet = WalletManager.getInstance()
|
||||
.createWallet(path, password, MNEMONIC_LANGUAGE);
|
||||
.createWallet(aFile, password, MNEMONIC_LANGUAGE);
|
||||
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
||||
if (!success) Log.e(TAG, newWallet.getErrorString());
|
||||
newWallet.close();
|
||||
@@ -380,8 +404,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
public void onGenerate(String name, String password, final String seed, final long restoreHeight) {
|
||||
createWallet(name, password,
|
||||
new WalletCreator() {
|
||||
public boolean createWallet(String path, String password) {
|
||||
Wallet newWallet = WalletManager.getInstance().recoveryWallet(path, seed, restoreHeight);
|
||||
public boolean createWallet(File aFile, String password) {
|
||||
Wallet newWallet = WalletManager.getInstance().recoveryWallet(aFile, seed, restoreHeight);
|
||||
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
||||
if (!success) Log.e(TAG, newWallet.getErrorString());
|
||||
newWallet.setPassword(password);
|
||||
@@ -397,9 +421,9 @@ public class LoginActivity extends AppCompatActivity
|
||||
final String address, final String viewKey, final String spendKey, final long restoreHeight) {
|
||||
createWallet(name, password,
|
||||
new WalletCreator() {
|
||||
public boolean createWallet(String path, String password) {
|
||||
public boolean createWallet(File aFile, String password) {
|
||||
Wallet newWallet = WalletManager.getInstance()
|
||||
.createWalletFromKeys(path, MNEMONIC_LANGUAGE, restoreHeight,
|
||||
.createWalletFromKeys(aFile, MNEMONIC_LANGUAGE, restoreHeight,
|
||||
address, viewKey, spendKey);
|
||||
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok);
|
||||
if (!success) Log.e(TAG, newWallet.getErrorString());
|
||||
|
||||
@@ -86,6 +86,8 @@ public class LoginFragment extends Fragment {
|
||||
|
||||
void onWalletDetails(final String wallet);
|
||||
|
||||
void onWalletReceive(final String wallet);
|
||||
|
||||
void onAddWallet();
|
||||
|
||||
void setTitle(String title);
|
||||
@@ -408,17 +410,18 @@ public class LoginFragment extends Fragment {
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
||||
String listItem = (String) listView.getItemAtPosition(info.position);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_info:
|
||||
String listItem = (String) listView.getItemAtPosition(info.position);
|
||||
return showInfo(listItem);
|
||||
case R.id.action_receive:
|
||||
return showReceive(listItem);
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean showInfo(String listItem) {
|
||||
|
||||
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
||||
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
@@ -436,4 +439,21 @@ public class LoginFragment extends Fragment {
|
||||
activityCallback.onWalletDetails(wallet);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean showReceive(String listItem) {
|
||||
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
||||
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
|
||||
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
|
||||
String x = isMainNet() ? "4" : "9A";
|
||||
if (x.indexOf(listItem.charAt(1)) < 0) {
|
||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
|
||||
activityCallback.onWalletReceive(wallet);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReceiveFragment extends Fragment {
|
||||
static final String TAG = "ReceiveFragment";
|
||||
|
||||
TextView tvAddress;
|
||||
EditText etPaymentId;
|
||||
EditText etAmount;
|
||||
Button bPaymentId;
|
||||
Button bGenerate;
|
||||
ImageView qrCode;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View view = inflater.inflate(R.layout.receive_fragment, container, false);
|
||||
|
||||
tvAddress = (TextView) view.findViewById(R.id.tvAddress);
|
||||
etPaymentId = (EditText) view.findViewById(R.id.etPaymentId);
|
||||
etAmount = (EditText) view.findViewById(R.id.etAmount);
|
||||
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
||||
qrCode = (ImageView) view.findViewById(R.id.qrCode);
|
||||
bGenerate = (Button) view.findViewById(R.id.bGenerate);
|
||||
|
||||
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
|
||||
Helper.showKeyboard(getActivity());
|
||||
etPaymentId.requestFocus();
|
||||
etPaymentId.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) {
|
||||
if (paymentIdOk()) {
|
||||
etAmount.requestFocus();
|
||||
} // otherwise ignore
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
etPaymentId.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
qrCode.setImageBitmap(null);
|
||||
if (paymentIdOk() && amountOk()) {
|
||||
bGenerate.setEnabled(true);
|
||||
} else {
|
||||
bGenerate.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
});
|
||||
|
||||
etAmount.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) {
|
||||
if (paymentIdOk() && amountOk()) {
|
||||
Helper.hideKeyboard(getActivity());
|
||||
generateQr();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
etAmount.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
qrCode.setImageBitmap(null);
|
||||
if (paymentIdOk() && amountOk()) {
|
||||
bGenerate.setEnabled(true);
|
||||
} else {
|
||||
bGenerate.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
});
|
||||
|
||||
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
etPaymentId.setText((Wallet.generatePaymentId()));
|
||||
etPaymentId.setSelection(etPaymentId.getText().length());
|
||||
if (paymentIdOk() && amountOk()) {
|
||||
generateQr();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bGenerate.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (paymentIdOk() && amountOk()) {
|
||||
Helper.hideKeyboard(getActivity());
|
||||
generateQr();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Bundle b = getArguments();
|
||||
String address = b.getString("address", "");
|
||||
tvAddress.setText(address);
|
||||
return view;
|
||||
}
|
||||
|
||||
private boolean amountOk() {
|
||||
String amountEntry = etAmount.getText().toString();
|
||||
if (amountEntry.isEmpty()) return true;
|
||||
long amount = Wallet.getAmountFromString(amountEntry);
|
||||
return (amount > 0);
|
||||
}
|
||||
|
||||
private boolean paymentIdOk() {
|
||||
String paymentId = etPaymentId.getText().toString();
|
||||
return paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId);
|
||||
}
|
||||
|
||||
private void generateQr() {
|
||||
String address = tvAddress.getText().toString();
|
||||
String paymentId = etPaymentId.getText().toString();
|
||||
String enteredAmount = etAmount.getText().toString();
|
||||
// that's a lot of converting ...
|
||||
String amount = (enteredAmount.isEmpty()?enteredAmount:Helper.getDisplayAmount(Wallet.getAmountFromString(enteredAmount)));
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(ScannerFragment.QR_SCHEME).append(address);
|
||||
boolean first = true;
|
||||
if (!paymentId.isEmpty()) {
|
||||
if (first) {
|
||||
sb.append("?");
|
||||
first = false;
|
||||
}
|
||||
sb.append(ScannerFragment.QR_PAYMENTID).append('=').append(paymentId);
|
||||
}
|
||||
if (!amount.isEmpty()) {
|
||||
if (first) {
|
||||
sb.append("?");
|
||||
} else {
|
||||
sb.append("&");
|
||||
}
|
||||
sb.append(ScannerFragment.QR_AMOUNT).append('=').append(amount);
|
||||
}
|
||||
String text = sb.toString();
|
||||
Bitmap qr = generate(text, 500, 500);
|
||||
if (qr != null) {
|
||||
qrCode.setImageBitmap(qr);
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap generate(String text, int width, int height) {
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
|
||||
try {
|
||||
BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
int[] pixels = new int[width * height];
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
if (bitMatrix.get(j, i)) {
|
||||
pixels[i * width + j] = 0x00000000;
|
||||
} else {
|
||||
pixels[i * height + j] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
|
||||
bitmap = addLogo(bitmap);
|
||||
return bitmap;
|
||||
} catch (WriterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Bitmap addLogo(Bitmap qrBitmap) {
|
||||
Bitmap logo = getMoneroLogo();
|
||||
int qrWidth = qrBitmap.getWidth();
|
||||
int qrHeight = qrBitmap.getHeight();
|
||||
int logoWidth = logo.getWidth();
|
||||
int logoHeight = logo.getHeight();
|
||||
|
||||
Bitmap logoBitmap = Bitmap.createBitmap(qrWidth, qrHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(logoBitmap);
|
||||
canvas.drawBitmap(qrBitmap, 0, 0, null);
|
||||
canvas.save(Canvas.ALL_SAVE_FLAG);
|
||||
// figure out how to scale the logo
|
||||
float scaleSize = 1.0f;
|
||||
while ((logoWidth / scaleSize) > (qrWidth / 5) || (logoHeight / scaleSize) > (qrHeight / 5)) {
|
||||
scaleSize *= 2;
|
||||
}
|
||||
float sx = 1.0f / scaleSize;
|
||||
canvas.scale(sx, sx, qrWidth / 2, qrHeight / 2);
|
||||
canvas.drawBitmap(logo, (qrWidth - logoWidth) / 2, (qrHeight - logoHeight) / 2, null);
|
||||
canvas.restore();
|
||||
return logoBitmap;
|
||||
}
|
||||
|
||||
private Bitmap logo = null;
|
||||
|
||||
private Bitmap getMoneroLogo() {
|
||||
if (logo == null) {
|
||||
logo = Helper.getBitmap(getContext(), R.drawable.ic_monero_qr);
|
||||
}
|
||||
return logo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -100,8 +100,8 @@ public class SendFragment extends Fragment {
|
||||
|
||||
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
||||
|
||||
etAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
etPaymentId.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
etAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
|
||||
Helper.showKeyboard(getActivity());
|
||||
@@ -209,7 +209,8 @@ public class SendFragment extends Fragment {
|
||||
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
etPaymentId.setText((activityCallback.generatePaymentId()));
|
||||
etPaymentId.setText((Wallet.generatePaymentId()));
|
||||
etPaymentId.setSelection(etPaymentId.getText().length());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -285,7 +286,7 @@ public class SendFragment extends Fragment {
|
||||
|
||||
private boolean paymentIdOk() {
|
||||
String paymentId = etPaymentId.getText().toString();
|
||||
return paymentId.isEmpty() || activityCallback.isPaymentIdValid(paymentId);
|
||||
return paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId);
|
||||
}
|
||||
|
||||
private void prepareSend() {
|
||||
@@ -358,10 +359,6 @@ public class SendFragment extends Fragment {
|
||||
|
||||
void onSend(String notes);
|
||||
|
||||
String generatePaymentId();
|
||||
|
||||
boolean isPaymentIdValid(String paymentId);
|
||||
|
||||
String getWalletAddress();
|
||||
|
||||
void onDisposeRequest();
|
||||
|
||||
@@ -561,16 +561,6 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generatePaymentId() {
|
||||
return getWallet().generatePaymentId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPaymentIdValid(String paymentId) {
|
||||
return Wallet.isPaymentIdValid(paymentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWalletAddress() {
|
||||
return getWallet().getAddress();
|
||||
|
||||
@@ -71,8 +71,8 @@ public class WalletManager {
|
||||
managedWallets.remove(walletId);
|
||||
}
|
||||
|
||||
public Wallet createWallet(String path, String password, String language) {
|
||||
long walletHandle = createWalletJ(path, password, language, isTestNet());
|
||||
public Wallet createWallet(File aFile, String password, String language) {
|
||||
long walletHandle = createWalletJ(aFile.getAbsolutePath(), password, language, isTestNet());
|
||||
Wallet wallet = new Wallet(walletHandle);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
@@ -89,14 +89,14 @@ public class WalletManager {
|
||||
|
||||
private native long openWalletJ(String path, String password, boolean isTestNet);
|
||||
|
||||
public Wallet recoveryWallet(String path, String mnemonic) {
|
||||
Wallet wallet = recoveryWallet(path, mnemonic, 0);
|
||||
public Wallet recoveryWallet(File aFile, String mnemonic) {
|
||||
Wallet wallet = recoveryWallet(aFile, mnemonic, 0);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public Wallet recoveryWallet(String path, String mnemonic, long restoreHeight) {
|
||||
long walletHandle = recoveryWalletJ(path, mnemonic, isTestNet(), restoreHeight);
|
||||
public Wallet recoveryWallet(File aFile, String mnemonic, long restoreHeight) {
|
||||
long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), mnemonic, isTestNet(), restoreHeight);
|
||||
Wallet wallet = new Wallet(walletHandle);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
@@ -104,9 +104,9 @@ public class WalletManager {
|
||||
|
||||
private native long recoveryWalletJ(String path, String mnemonic, boolean isTestNet, long restoreHeight);
|
||||
|
||||
public Wallet createWalletFromKeys(String path, String language, long restoreHeight,
|
||||
public Wallet createWalletFromKeys(File aFile, String language, long restoreHeight,
|
||||
String addressString, String viewKeyString, String spendKeyString) {
|
||||
long walletHandle = createWalletFromKeysJ(path, language, isTestNet(), restoreHeight,
|
||||
long walletHandle = createWalletFromKeysJ(aFile.getAbsolutePath(), language, isTestNet(), restoreHeight,
|
||||
addressString, viewKeyString, spendKeyString);
|
||||
Wallet wallet = new Wallet(walletHandle);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
@@ -134,6 +134,10 @@ public class WalletManager {
|
||||
return closed;
|
||||
}
|
||||
|
||||
public boolean walletExists(File aFile) {
|
||||
return walletExists(aFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
public native boolean walletExists(String path);
|
||||
|
||||
public native boolean verifyWalletPassword(String keys_file_name, String password, boolean watch_only);
|
||||
@@ -146,6 +150,31 @@ public class WalletManager {
|
||||
public String address;
|
||||
}
|
||||
|
||||
public WalletInfo getWalletInfo(File wallet) {
|
||||
WalletInfo info = new WalletInfo();
|
||||
info.path = wallet.getParentFile();
|
||||
info.name = wallet.getName();
|
||||
File addressFile = new File(info.path, info.name + ".address.txt");
|
||||
//Log.d(TAG, addressFile.getAbsolutePath());
|
||||
info.address = "??????";
|
||||
BufferedReader addressReader = null;
|
||||
try {
|
||||
addressReader = new BufferedReader(new FileReader(addressFile));
|
||||
info.address = addressReader.readLine();
|
||||
} catch (IOException ex) {
|
||||
Log.d(TAG, ex.getLocalizedMessage());
|
||||
} finally {
|
||||
if (addressReader != null) {
|
||||
try {
|
||||
addressReader.close();
|
||||
} catch (IOException ex) {
|
||||
// that's just too bad
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public List<WalletInfo> findWallets(File path) {
|
||||
List<WalletInfo> wallets = new ArrayList<>();
|
||||
Log.d(TAG, "Scanning: " + path.getAbsolutePath());
|
||||
@@ -155,29 +184,9 @@ public class WalletManager {
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < found.length; i++) {
|
||||
WalletInfo info = new WalletInfo();
|
||||
info.path = path;
|
||||
String filename = found[i].getName();
|
||||
info.name = filename.substring(0, filename.length() - 5); // 5 is length of ".keys"+1
|
||||
File addressFile = new File(path, info.name + ".address.txt");
|
||||
//Log.d(TAG, addressFile.getAbsolutePath());
|
||||
info.address = "??????";
|
||||
BufferedReader addressReader = null;
|
||||
try {
|
||||
addressReader = new BufferedReader(new FileReader(addressFile));
|
||||
info.address = addressReader.readLine();
|
||||
} catch (IOException ex) {
|
||||
Log.d(TAG, ex.getLocalizedMessage());
|
||||
} finally {
|
||||
if (addressReader != null) {
|
||||
try {
|
||||
addressReader.close();
|
||||
} catch (IOException ex) {
|
||||
// that's just too bad
|
||||
}
|
||||
}
|
||||
}
|
||||
wallets.add(info);
|
||||
File f = new File(found[i].getParent(), filename.substring(0, filename.length() - 5)); // 5 is length of ".keys"+1
|
||||
wallets.add(getWalletInfo(f));
|
||||
}
|
||||
return wallets;
|
||||
}
|
||||
|
||||
@@ -527,7 +527,7 @@ public class WalletService extends Service {
|
||||
}
|
||||
|
||||
private Wallet openWallet(String walletName, String walletPassword) {
|
||||
String path = Helper.getWalletPath(getApplicationContext(), walletName);
|
||||
String path = Helper.getWalletFile(getApplicationContext(), walletName).getAbsolutePath();
|
||||
showProgress(20);
|
||||
Wallet wallet = null;
|
||||
WalletManager walletMgr = WalletManager.getInstance();
|
||||
@@ -557,7 +557,7 @@ public class WalletService extends Service {
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
|
||||
Notification notification = new Notification.Builder(this)
|
||||
.setContentTitle(getString(R.string.service_description))
|
||||
.setSmallIcon(R.drawable.ic_notification_sync_32_32)
|
||||
.setSmallIcon(R.drawable.ic_monero_32dp)
|
||||
.setContentIntent(pendingIntent)
|
||||
.build();
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
|
||||
@@ -21,7 +21,14 @@ import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.VectorDrawable;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
@@ -91,12 +98,16 @@ public class Helper {
|
||||
}
|
||||
}
|
||||
|
||||
static public String getWalletPath(Context context, String aWalletName) {
|
||||
// static public String getWalletPath(Context context, String aWalletName) {
|
||||
// return getWalletFile(context, aWalletName).getAbsolutePath();
|
||||
// }
|
||||
|
||||
static public File getWalletFile(Context context, String aWalletName) {
|
||||
File walletDir = getStorageRoot(context);
|
||||
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
||||
File f = new File(walletDir, aWalletName);
|
||||
Log.d(TAG, "wallet = " + f.getAbsolutePath() + " size=" + f.length());
|
||||
return f.getAbsolutePath();
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Checks if external storage is available for read and write */
|
||||
@@ -136,6 +147,7 @@ public class Helper {
|
||||
return ((address.length() == 95) && ("4".indexOf(address.charAt(0)) >= 0));
|
||||
}
|
||||
}
|
||||
|
||||
static public String getDisplayAmount(long amount) {
|
||||
String s = Wallet.getDisplayAmount(amount);
|
||||
int lastZero = 0;
|
||||
@@ -152,4 +164,25 @@ public class Helper {
|
||||
int cutoff = Math.max(lastZero, decimal + 2);
|
||||
return s.substring(0, cutoff);
|
||||
}
|
||||
|
||||
public static Bitmap getBitmap(Context context, int drawableId) {
|
||||
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
return BitmapFactory.decodeResource(context.getResources(), drawableId);
|
||||
} else if (drawable instanceof VectorDrawable) {
|
||||
return getBitmap((VectorDrawable) drawable);
|
||||
} else {
|
||||
throw new IllegalArgumentException("unsupported drawable type");
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap getBitmap(VectorDrawable vectorDrawable) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
|
||||
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
vectorDrawable.draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportHeight="75.0"
|
||||
android:viewportWidth="75.0">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData=" M 37.3, 37.3
|
||||
m -36.9, 0
|
||||
a 36.9,36.9 0 1,0 73.8,0
|
||||
a 36.9,36.9 0 1,0 -73.8,0" />
|
||||
|
||||
<path
|
||||
android:fillColor="#ff6600"
|
||||
android:pathData="m 37.3,0.35329395 c -20.377,0 -36.903,16.524 -36.903,36.902 0,4.074 0.66,7.992 1.88,11.657 l 11.036,0 0,-31.049 23.987,23.987 23.987,-23.987 0,31.049 11.037,0 c 1.22,-3.665 1.88,-7.583 1.88,-11.657 0,-20.378 -16.526,-36.902 -36.904,-36.902" />
|
||||
<path
|
||||
android:fillColor="#4c4c4c"
|
||||
android:pathData="m 21.3164,36.895994 0,19.537 -15.55,0 c 6.478,10.628 18.178,17.726 31.533,17.726 13.355,0 25.056,-7.098 31.533,-17.726 l -15.549,0 0,-19.537 -15.984,15.984 z" />
|
||||
|
||||
</vector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="50dp"
|
||||
android:height="50dp"
|
||||
android:viewportHeight="75.0"
|
||||
android:viewportWidth="75.0">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData=" M 37.3, 37.3
|
||||
m -36.9, 0
|
||||
a 36.9,36.9 0 1,0 73.8,0
|
||||
a 36.9,36.9 0 1,0 -73.8,0" />
|
||||
|
||||
<path
|
||||
android:fillColor="#ff6600"
|
||||
android:pathData="m 37.3,0.35329395 c -20.377,0 -36.903,16.524 -36.903,36.902 0,4.074 0.66,7.992 1.88,11.657 l 11.036,0 0,-31.049 23.987,23.987 23.987,-23.987 0,31.049 11.037,0 c 1.22,-3.665 1.88,-7.583 1.88,-11.657 0,-20.378 -16.526,-36.902 -36.904,-36.902" />
|
||||
<path
|
||||
android:fillColor="#4c4c4c"
|
||||
android:pathData="m 21.3164,36.895994 0,19.537 -15.55,0 c 6.478,10.628 18.178,17.726 31.533,17.726 13.355,0 25.056,-7.098 31.533,-17.726 l -15.549,0 0,-19.537 -15.984,15.984 z" />
|
||||
|
||||
</vector>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAddress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4sp"
|
||||
android:layout_marginTop="4sp"
|
||||
android:hint="@string/send_address_hint"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4sp"
|
||||
android:layout_marginTop="4sp"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="10">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="8sp"
|
||||
android:layout_weight="3"
|
||||
android:text="@string/receive_paymentid_hint"
|
||||
android:textAlignment="textEnd"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPaymentId"
|
||||
android:layout_width="0sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="5"
|
||||
android:hint="@string/send_paymentid_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="textStart"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bPaymentId"
|
||||
android:layout_width="0sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="2"
|
||||
android:background="@color/colorPrimary"
|
||||
android:enabled="true"
|
||||
android:minHeight="36sp"
|
||||
android:text="@string/receive_paymentid_button"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="4sp"
|
||||
android:layout_marginTop="4sp"
|
||||
android:weightSum="10">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="8sp"
|
||||
android:layout_weight="3"
|
||||
android:text="@string/send_amount_label"
|
||||
android:textAlignment="textEnd"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etAmount"
|
||||
android:layout_width="0sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/send_amount_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="numberDecimal"
|
||||
android:layout_weight="7"
|
||||
android:textAlignment="textStart"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/bGenerate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4sp"
|
||||
android:layout_marginTop="4sp"
|
||||
android:minHeight="36sp"
|
||||
android:background="@color/colorPrimary"
|
||||
android:text="@string/receive_generate_hint" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrCode"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16sp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/ic_monero_32dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -5,4 +5,8 @@
|
||||
android:id="@+id/action_info"
|
||||
android:title="@string/menu_info" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_receive"
|
||||
android:title="@string/menu_receive" />
|
||||
|
||||
</menu>
|
||||
@@ -4,6 +4,7 @@
|
||||
<string name="wallet_activity_name">Wallet</string>
|
||||
|
||||
<string name="menu_info">Details</string>
|
||||
<string name="menu_receive">Receive</string>
|
||||
|
||||
<string name="prompt_daemon">[<user>:<pass>@]<daemon>[:<port>]</string>
|
||||
<string name="prompt_mainnet">Net Selection</string>
|
||||
@@ -151,6 +152,10 @@
|
||||
<string name="tx_pending">PENDING</string>
|
||||
<string name="tx_failed">FAILED</string>
|
||||
|
||||
<string name="receive_generate_hint">Generate QR Code</string>
|
||||
<string name="receive_paymentid_button">Generate</string>
|
||||
<string name="receive_paymentid_hint">PaymentID</string>
|
||||
|
||||
<string name="big_amount">999999.999999999999</string>
|
||||
|
||||
<string-array name="mixin">
|
||||
|
||||
Reference in New Issue
Block a user