mirror of https://github.com/m2049r/xmrwallet.git
check daemon availability
show txs immediately only save on first sync no store on close Increased Version
This commit is contained in:
parent
cb5795e64b
commit
95e47e3407
|
@ -89,6 +89,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/cmake" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/cmake" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||||
|
|
|
@ -7,8 +7,8 @@ android {
|
||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 2
|
versionCode 3
|
||||||
versionName "0.2.0"
|
versionName "0.3.0"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
|
|
@ -386,8 +386,9 @@ Java_com_m2049r_xmrwallet_model_WalletManager_setDaemonAddressJ(JNIEnv *env, job
|
||||||
env->ReleaseStringUTFChars(address, _address);
|
env->ReleaseStringUTFChars(address, _address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns whether the daemon can be reached, and its version number
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_m2049r_xmrwallet_model_WalletManager_getConnectedDaemonVersion(JNIEnv *env,
|
Java_com_m2049r_xmrwallet_model_WalletManager_getDaemonVersion(JNIEnv *env,
|
||||||
jobject instance) {
|
jobject instance) {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
bool isConnected =
|
bool isConnected =
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -25,6 +25,7 @@ import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.StrictMode;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
@ -46,11 +47,19 @@ import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class LoginActivity extends Activity {
|
public class LoginActivity extends Activity {
|
||||||
static final String TAG = "LoginActivity";
|
static final String TAG = "LoginActivity";
|
||||||
|
|
||||||
|
static final int MIN_DAEMON_VERSION = 65544;
|
||||||
|
static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms
|
||||||
|
|
||||||
ListView listView;
|
ListView listView;
|
||||||
List<String> walletList = new ArrayList<>();
|
List<String> walletList = new ArrayList<>();
|
||||||
List<String> displayedList = new ArrayList<>();
|
List<String> displayedList = new ArrayList<>();
|
||||||
|
@ -124,9 +133,17 @@ public class LoginActivity extends Activity {
|
||||||
|
|
||||||
final int preambleLength = "[123456] ".length();
|
final int preambleLength = "[123456] ".length();
|
||||||
if (itemValue.length() <= (preambleLength)) {
|
if (itemValue.length() <= (preambleLength)) {
|
||||||
Toast.makeText(LoginActivity.this, "something's wrong", Toast.LENGTH_LONG).show();
|
Toast.makeText(LoginActivity.this, getString(R.string.panic), Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setWalletDaemon();
|
||||||
|
if (!checkWalletDaemon()) {
|
||||||
|
Toast.makeText(LoginActivity.this, getString(R.string.warn_daemon_unavailable), Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// looking good
|
||||||
|
savePrefs(false);
|
||||||
|
|
||||||
String wallet = itemValue.substring(preambleLength);
|
String wallet = itemValue.substring(preambleLength);
|
||||||
promptPassword(wallet);
|
promptPassword(wallet);
|
||||||
|
@ -200,6 +217,32 @@ public class LoginActivity extends Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkWalletDaemon() {
|
||||||
|
// if (android.os.Build.VERSION.SDK_INT > 9) {
|
||||||
|
StrictMode.ThreadPolicy prevPolicy = StrictMode.getThreadPolicy();
|
||||||
|
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder(prevPolicy).permitNetwork().build();
|
||||||
|
StrictMode.setThreadPolicy(policy);
|
||||||
|
String d[] = WalletManager.getInstance().getDaemonAddress().split(":");
|
||||||
|
String host = d[0];
|
||||||
|
int port = Integer.parseInt(d[1]);
|
||||||
|
Socket socket = new Socket();
|
||||||
|
long a = new Date().getTime();
|
||||||
|
try {
|
||||||
|
socket.connect(new InetSocketAddress(host, port), DAEMON_TIMEOUT);
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Log.d(TAG, "Cannot reach daemon " + host + ":" + port + " because " + ex.getLocalizedMessage());
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
StrictMode.setThreadPolicy(prevPolicy);
|
||||||
|
}
|
||||||
|
long b = new Date().getTime();
|
||||||
|
Log.d(TAG, "Daemon is " + (b - a) + "ms away.");
|
||||||
|
int version = WalletManager.getInstance().getDaemonVersion();
|
||||||
|
Log.d(TAG, "Daemon is v" + version);
|
||||||
|
return (version >= MIN_DAEMON_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkWalletPassword(String walletName, String password) {
|
private boolean checkWalletPassword(String walletName, String password) {
|
||||||
String walletPath = new File(Helper.getStorageRoot(getApplicationContext()),
|
String walletPath = new File(Helper.getStorageRoot(getApplicationContext()),
|
||||||
walletName + ".keys").getAbsolutePath();
|
walletName + ".keys").getAbsolutePath();
|
||||||
|
@ -207,7 +250,6 @@ public class LoginActivity extends Activity {
|
||||||
return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true);
|
return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Log.d(TAG, "onPause()");
|
||||||
|
@ -215,6 +257,12 @@ public class LoginActivity extends Activity {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Log.d(TAG, "onResume()");
|
||||||
|
}
|
||||||
|
|
||||||
boolean isMainNet() {
|
boolean isMainNet() {
|
||||||
ToggleButton tbMainNet = (ToggleButton) findViewById(R.id.tbMainNet);
|
ToggleButton tbMainNet = (ToggleButton) findViewById(R.id.tbMainNet);
|
||||||
return tbMainNet.isChecked();
|
return tbMainNet.isChecked();
|
||||||
|
@ -275,19 +323,20 @@ public class LoginActivity extends Activity {
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
void startWallet(String walletName, String walletPassword) {
|
private void setWalletDaemon() {
|
||||||
Log.d(TAG, "startWallet()");
|
|
||||||
savePrefs(false);
|
|
||||||
boolean testnet = !isMainNet();
|
boolean testnet = !isMainNet();
|
||||||
String daemon = getDaemon();
|
String daemon = getDaemon();
|
||||||
|
|
||||||
Intent intent = new Intent(getApplicationContext(), WalletActivity.class);
|
|
||||||
if (!daemon.contains(":")) {
|
if (!daemon.contains(":")) {
|
||||||
daemon = daemon + (testnet ? ":28081" : ":18081");
|
daemon = daemon + (testnet ? ":28081" : ":18081");
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletManager.getInstance().setDaemon(daemon, testnet);
|
WalletManager.getInstance().setDaemon(daemon, testnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startWallet(String walletName, String walletPassword) {
|
||||||
|
Log.d(TAG, "startWallet()");
|
||||||
|
Intent intent = new Intent(getApplicationContext(), WalletActivity.class);
|
||||||
intent.putExtra(WalletActivity.REQUEST_ID, walletName);
|
intent.putExtra(WalletActivity.REQUEST_ID, walletName);
|
||||||
intent.putExtra(WalletActivity.REQUEST_PW, walletPassword);
|
intent.putExtra(WalletActivity.REQUEST_PW, walletPassword);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
@ -332,7 +381,7 @@ public class LoginActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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_WRITE_EXTERNAL_STORAGE:
|
case Helper.PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE:
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -97,6 +97,7 @@ public class WalletActivity extends AppCompatActivity
|
||||||
Log.d(TAG, "onStop()");
|
Log.d(TAG, "onStop()");
|
||||||
releaseWakeLock();
|
releaseWakeLock();
|
||||||
disconnectWalletService();
|
disconnectWalletService();
|
||||||
|
this.synced = false;
|
||||||
super.onStop();
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +146,7 @@ public class WalletActivity extends AppCompatActivity
|
||||||
balanceView.setText(Wallet.getDisplayAmount(wallet.getBalance()));
|
balanceView.setText(Wallet.getDisplayAmount(wallet.getBalance()));
|
||||||
unlockedView.setText(Wallet.getDisplayAmount(wallet.getUnlockedBalance()));
|
unlockedView.setText(Wallet.getDisplayAmount(wallet.getUnlockedBalance()));
|
||||||
String sync = "";
|
String sync = "";
|
||||||
|
// TODO: getConnectionStatus() blocks as it tries to connect - this is bad in the UI thread!
|
||||||
if (wallet.getConnectionStatus() == Wallet.ConnectionStatus.ConnectionStatus_Connected) {
|
if (wallet.getConnectionStatus() == Wallet.ConnectionStatus.ConnectionStatus_Connected) {
|
||||||
if (!wallet.isSynchronized()) {
|
if (!wallet.isSynchronized()) {
|
||||||
long n = wallet.getDaemonBlockChainHeight() - wallet.getBlockChainHeight();
|
long n = wallet.getDaemonBlockChainHeight() - wallet.getBlockChainHeight();
|
||||||
|
@ -160,13 +162,19 @@ public class WalletActivity extends AppCompatActivity
|
||||||
sync = getString(R.string.status_synced) + ": " + wallet.getBlockChainHeight();
|
sync = getString(R.string.status_synced) + ": " + wallet.getBlockChainHeight();
|
||||||
if (!synced) {
|
if (!synced) {
|
||||||
hideProgress();
|
hideProgress();
|
||||||
|
saveWallet(); // save ONLY on first sync
|
||||||
|
// the usual use case is:
|
||||||
|
// open the wallet, wait for sync, check balance, close app
|
||||||
|
// even if we wait for new transactions, they will be synced and saved next time
|
||||||
|
// the advantage here is that we are storing the state while the app is open
|
||||||
|
// and don't get into timing issues
|
||||||
synced = true;
|
synced = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String t = (wallet.isTestNet() ? getString(R.string.connect_testnet) : getString(R.string.connect_mainnet));
|
String net = (wallet.isTestNet() ? getString(R.string.connect_testnet) : getString(R.string.connect_mainnet));
|
||||||
syncProgressView.setText(sync);
|
syncProgressView.setText(sync);
|
||||||
connectionStatusView.setText(t + " " + wallet.getConnectionStatus().toString().substring(17));
|
connectionStatusView.setText(net + " " + wallet.getConnectionStatus().toString().substring(17));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -241,11 +249,22 @@ public class WalletActivity extends AppCompatActivity
|
||||||
mBoundService.setObserver(null);
|
mBoundService.setObserver(null);
|
||||||
unbindService(mConnection);
|
unbindService(mConnection);
|
||||||
mIsBound = false;
|
mIsBound = false;
|
||||||
Toast.makeText(getApplicationContext(), getString(R.string.status_wallet_unloading), Toast.LENGTH_LONG).show();
|
|
||||||
Log.d(TAG, "UNBOUND");
|
Log.d(TAG, "UNBOUND");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveWallet() {
|
||||||
|
if (mIsBound) { // no point in talking to unbound service
|
||||||
|
Intent intent = new Intent(getApplicationContext(), WalletService.class);
|
||||||
|
intent.putExtra(WalletService.REQUEST, WalletService.REQUEST_CMD_STORE);
|
||||||
|
startService(intent);
|
||||||
|
Toast.makeText(getApplicationContext(), getString(R.string.status_wallet_unloading), Toast.LENGTH_LONG).show();
|
||||||
|
Log.d(TAG, "STORE request sent");
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Service not bound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Callbacks from TransactionInfoAdapter
|
// Callbacks from TransactionInfoAdapter
|
||||||
@Override
|
@Override
|
||||||
public void onInteraction(final View view, final TransactionInfo infoItem) {
|
public void onInteraction(final View view, final TransactionInfo infoItem) {
|
||||||
|
@ -279,6 +298,7 @@ public class WalletActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Log.d(TAG, "onPause()");
|
||||||
|
//saveWallet(); //TODO: do it here if we really need to ...
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -38,10 +38,10 @@ import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
|
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
|
||||||
static final String TAG = "TransactionInfoAdapter";
|
private static final String TAG = "TransactionInfoAdapter";
|
||||||
|
|
||||||
static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
|
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("HH:mm:ss");
|
private static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
|
||||||
static final int TX_RED = Color.rgb(255, 79, 65);
|
static final int TX_RED = Color.rgb(255, 79, 65);
|
||||||
static final int TX_GREEN = Color.rgb(54, 176, 91);
|
static final int TX_GREEN = Color.rgb(54, 176, 91);
|
||||||
|
@ -100,15 +100,15 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
public final TextView tvAmount;
|
final TextView tvAmount;
|
||||||
public final TextView tvAmountPoint;
|
final TextView tvAmountPoint;
|
||||||
public final TextView tvAmountDecimal;
|
final TextView tvAmountDecimal;
|
||||||
public final TextView tvDate;
|
final TextView tvDate;
|
||||||
public final TextView tvTime;
|
final TextView tvTime;
|
||||||
public TransactionInfo infoItem;
|
TransactionInfo infoItem;
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
this.tvAmount = (TextView) itemView.findViewById(R.id.tx_amount);
|
this.tvAmount = (TextView) itemView.findViewById(R.id.tx_amount);
|
||||||
// I know this is stupid but can't be bothered to align decimals otherwise
|
// I know this is stupid but can't be bothered to align decimals otherwise
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -23,7 +23,7 @@ public class TransactionInfo {
|
||||||
|
|
||||||
public long handle;
|
public long handle;
|
||||||
|
|
||||||
public TransactionInfo(long handle) {
|
TransactionInfo(long handle) {
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -35,7 +35,7 @@ public class Wallet {
|
||||||
private long handle = 0;
|
private long handle = 0;
|
||||||
private long listenerHandle = 0;
|
private long listenerHandle = 0;
|
||||||
|
|
||||||
public Wallet(long handle) {
|
Wallet(long handle) {
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -29,7 +29,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class WalletManager {
|
public class WalletManager {
|
||||||
final static String TAG = "WalletManager";
|
private final static String TAG = "WalletManager";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("monerujo");
|
System.loadLibrary("monerujo");
|
||||||
|
@ -204,7 +204,7 @@ public class WalletManager {
|
||||||
|
|
||||||
private native void setDaemonAddressJ(String address);
|
private native void setDaemonAddressJ(String address);
|
||||||
|
|
||||||
public native int getConnectedDaemonVersion();
|
public native int getDaemonVersion();
|
||||||
|
|
||||||
public native long getBlockchainHeight();
|
public native long getBlockchainHeight();
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -16,9 +16,7 @@
|
||||||
|
|
||||||
package com.m2049r.xmrwallet.service;
|
package com.m2049r.xmrwallet.service;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -27,10 +25,8 @@ import android.os.HandlerThread;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.PowerManager;
|
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.R;
|
import com.m2049r.xmrwallet.R;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
@ -47,10 +43,11 @@ import com.m2049r.xmrwallet.util.Helper;
|
||||||
public class WalletService extends Service {
|
public class WalletService extends Service {
|
||||||
final static String TAG = "WalletService";
|
final static String TAG = "WalletService";
|
||||||
|
|
||||||
public static final String REQUEST = "request";
|
|
||||||
public static final String REQUEST_WALLET = "wallet";
|
public static final String REQUEST_WALLET = "wallet";
|
||||||
|
public static final String REQUEST = "request";
|
||||||
public static final String REQUEST_CMD_LOAD = "load";
|
public static final String REQUEST_CMD_LOAD = "load";
|
||||||
public static final String REQUEST_CMD_LOAD_PW = "walletPassword";
|
public static final String REQUEST_CMD_LOAD_PW = "walletPassword";
|
||||||
|
public static final String REQUEST_CMD_STORE = "store";
|
||||||
|
|
||||||
public static final int START_SERVICE = 1;
|
public static final int START_SERVICE = 1;
|
||||||
public static final int STOP_SERVICE = 2;
|
public static final int STOP_SERVICE = 2;
|
||||||
|
@ -70,7 +67,7 @@ public class WalletService extends Service {
|
||||||
this.wallet = aWallet;
|
this.wallet = aWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
void start() {
|
||||||
Log.d(TAG, "MyWalletListener.start()");
|
Log.d(TAG, "MyWalletListener.start()");
|
||||||
if (wallet == null) throw new IllegalStateException("No wallet!");
|
if (wallet == null) throw new IllegalStateException("No wallet!");
|
||||||
//acquireWakeLock();
|
//acquireWakeLock();
|
||||||
|
@ -78,7 +75,7 @@ public class WalletService extends Service {
|
||||||
wallet.startRefresh();
|
wallet.startRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
void stop() {
|
||||||
Log.d(TAG, "MyWalletListener.stop()");
|
Log.d(TAG, "MyWalletListener.stop()");
|
||||||
if (wallet == null) throw new IllegalStateException("No wallet!");
|
if (wallet == null) throw new IllegalStateException("No wallet!");
|
||||||
wallet.pauseRefresh();
|
wallet.pauseRefresh();
|
||||||
|
@ -178,7 +175,7 @@ public class WalletService extends Service {
|
||||||
|
|
||||||
// Handler that receives messages from the thread
|
// Handler that receives messages from the thread
|
||||||
private final class ServiceHandler extends Handler {
|
private final class ServiceHandler extends Handler {
|
||||||
public ServiceHandler(Looper looper) {
|
ServiceHandler(Looper looper) {
|
||||||
super(looper);
|
super(looper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,11 +185,19 @@ public class WalletService extends Service {
|
||||||
switch (msg.arg2) {
|
switch (msg.arg2) {
|
||||||
case START_SERVICE: {
|
case START_SERVICE: {
|
||||||
Bundle extras = msg.getData();
|
Bundle extras = msg.getData();
|
||||||
String walletId = extras.getString(REQUEST_WALLET, null);
|
String cmd = extras.getString(REQUEST, null);
|
||||||
String walletPw = extras.getString(REQUEST_CMD_LOAD_PW, null);
|
if (cmd.equals(REQUEST_CMD_LOAD)) {
|
||||||
Log.d(TAG, "LOAD wallet " + walletId);// + ":" + walletPw);
|
String walletId = extras.getString(REQUEST_WALLET, null);
|
||||||
if (walletId != null) {
|
String walletPw = extras.getString(REQUEST_CMD_LOAD_PW, null);
|
||||||
start(walletId, walletPw); // TODO What if this fails?
|
Log.d(TAG, "LOAD wallet " + walletId);// + ":" + walletPw);
|
||||||
|
if (walletId != null) {
|
||||||
|
start(walletId, walletPw); // TODO What if this fails?
|
||||||
|
}
|
||||||
|
} else if (cmd.equals(REQUEST_CMD_STORE)) {
|
||||||
|
Wallet myWallet = getWallet();
|
||||||
|
Log.d(TAG, "storing wallet: " + myWallet.getName());
|
||||||
|
getWallet().store();
|
||||||
|
Log.d(TAG, "wallet stored: " + myWallet.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -251,7 +256,6 @@ public class WalletService extends Service {
|
||||||
// this should not matter since the old activity is not getting updates
|
// this should not matter since the old activity is not getting updates
|
||||||
// and the new one is not listening yet (although it will be bound)
|
// and the new one is not listening yet (although it will be bound)
|
||||||
Log.d(TAG, "onStartCommand()");
|
Log.d(TAG, "onStartCommand()");
|
||||||
//acquireWakeLock(); // we want to be awake for the fun stuff
|
|
||||||
// For each start request, send a message to start a job and deliver the
|
// For each start request, send a message to start a job and deliver the
|
||||||
// start ID so we know which request we're stopping when we finish the job
|
// start ID so we know which request we're stopping when we finish the job
|
||||||
Message msg = mServiceHandler.obtainMessage();
|
Message msg = mServiceHandler.obtainMessage();
|
||||||
|
@ -293,6 +297,11 @@ public class WalletService extends Service {
|
||||||
showProgress(95);
|
showProgress(95);
|
||||||
}
|
}
|
||||||
Log.d(TAG, "start() done");
|
Log.d(TAG, "start() done");
|
||||||
|
if (observer != null) {
|
||||||
|
Wallet myWallet = getWallet();
|
||||||
|
myWallet.getHistory().refresh();
|
||||||
|
observer.onRefreshed(myWallet, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (c) 2017 m2049r
|
* Copyright (c) 2017 m2049r
|
||||||
* <p>
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
* <p>
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* <p>
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -28,8 +28,8 @@ import com.m2049r.xmrwallet.R;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class Helper {
|
public class Helper {
|
||||||
static final String TAG = "Helper";
|
private static final String TAG = "Helper";
|
||||||
static final String WALLET_DIR = "Monerujo";
|
private static final String WALLET_DIR = "Monerujo";
|
||||||
|
|
||||||
static public File getStorageRoot(Context context) {
|
static public File getStorageRoot(Context context) {
|
||||||
if (!isExternalStorageWritable()) {
|
if (!isExternalStorageWritable()) {
|
||||||
|
@ -79,10 +79,7 @@ public class Helper {
|
||||||
/* Checks if external storage is available for read and write */
|
/* Checks if external storage is available for read and write */
|
||||||
static public boolean isExternalStorageWritable() {
|
static public boolean isExternalStorageWritable() {
|
||||||
String state = Environment.getExternalStorageState();
|
String state = Environment.getExternalStorageState();
|
||||||
if (Environment.MEDIA_MOUNTED.equals(state)) {
|
return Environment.MEDIA_MOUNTED.equals(state);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
android:textSize="10sp"
|
android:textSize="10sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:text="Connecting..."
|
android:text="Loading..."
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
android:textSize="10sp"
|
android:textSize="10sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:text="Connecting..."
|
android:text="Loading..."
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/tvConnectionStatus" />
|
app:layout_constraintTop_toBottomOf="@+id/tvConnectionStatus" />
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/llProgress"
|
android:id="@+id/llProgress"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:visibility="gone" >
|
android:visibility="gone" >
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:text="Connecting..." />
|
android:text="Loading..." />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/pbProgress"
|
android:id="@+id/pbProgress"
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
<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="prompt_daemon_missing">Daemon address must be set!</string>
|
<string name="prompt_daemon_missing">Daemon address must be set!</string>
|
||||||
<string name="prompt_wrong_net">Daemon does not fit wallet!</string>
|
<string name="prompt_wrong_net">Daemon type does not fit to wallet!</string>
|
||||||
|
<string name="warn_daemon_unavailable">Warning: cannot reach daemon!</string>
|
||||||
|
<string name="panic">Something\'s wrong!</string>
|
||||||
|
|
||||||
<string name="title_amount">Amount</string>
|
<string name="title_amount">Amount</string>
|
||||||
<string name="title_date">Date</string>
|
<string name="title_date">Date</string>
|
||||||
|
|
Binary file not shown.
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module external.linked.project.id="xmrwallet" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
<module external.linked.project.id="xmrwallet" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" version="4">
|
||||||
<component name="FacetManager">
|
<component name="FacetManager">
|
||||||
<facet type="java-gradle" name="Java-Gradle">
|
<facet type="java-gradle" name="Java-Gradle">
|
||||||
<configuration>
|
<configuration>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
Loading…
Reference in New Issue