lots of minor fixes & tweaks. do not copy cache.

the cache file is corrupt after recovery (except watch only).
This commit is contained in:
m2049r 2017-08-17 10:57:24 +02:00
parent 032aa24ab5
commit 9f38b957e1
6 changed files with 149 additions and 100 deletions

View File

@ -302,7 +302,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobje
return reinterpret_cast<jlong>(wallet);
}
JNIEXPORT jboolean JNICALL
JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_createWalletFromKeysJ(JNIEnv *env, jobject instance,
jstring path, jstring language,
jboolean isTestNet,

View File

@ -21,7 +21,6 @@ import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@ -38,8 +37,6 @@ import com.m2049r.xmrwallet.util.Helper;
import java.io.File;
// TODO: somehow show which net we are generating for
public class GenerateFragment extends Fragment {
static final String TAG = "GenerateFragment";
@ -119,7 +116,11 @@ public class GenerateFragment extends Fragment {
etWalletPassword.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)) {
etWalletMnemonic.requestFocus();
if (etWalletAddress.length() > 0) {
etWalletAddress.requestFocus();
} else {
etWalletMnemonic.requestFocus();
}
return true;
}
return false;
@ -141,39 +142,45 @@ public class GenerateFragment extends Fragment {
return false;
}
});
etWalletMnemonic.setOnClickListener(new View.OnClickListener() {
etWalletMnemonic.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Helper.showKeyboard(getActivity());
}
});
etWalletMnemonic.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
if (etWalletMnemonic.length() > 0) {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
etWalletAddress.setVisibility(View.INVISIBLE);
} else {
etWalletAddress.setVisibility(View.VISIBLE);
if (etWalletAddress.length() == 0) {
etWalletRestoreHeight.setVisibility(View.INVISIBLE);
} else {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
}
etWalletMnemonic.addTextChangedListener(new
}
}
TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
if (etWalletMnemonic.length() > 0) {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
etWalletAddress.setVisibility(View.INVISIBLE);
} else {
etWalletAddress.setVisibility(View.VISIBLE);
if (etWalletAddress.length() == 0) {
etWalletRestoreHeight.setVisibility(View.INVISIBLE);
} else {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
etWalletAddress.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
etWalletAddress.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 (etWalletAddress.length() == 0) {
@ -191,40 +198,46 @@ public class GenerateFragment extends Fragment {
return false;
}
});
etWalletAddress.setOnClickListener(new View.OnClickListener() {
etWalletAddress.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Helper.showKeyboard(getActivity());
}
});
etWalletAddress.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
if (etWalletAddress.length() > 0) {
llRestoreKeys.setVisibility(View.VISIBLE);
etWalletMnemonic.setVisibility(View.INVISIBLE);
etWalletRestoreHeight.setVisibility(View.VISIBLE);
} else {
llRestoreKeys.setVisibility(View.INVISIBLE);
etWalletMnemonic.setVisibility(View.VISIBLE);
if (etWalletMnemonic.length() == 0) {
etWalletRestoreHeight.setVisibility(View.INVISIBLE);
} else {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
}
}
}
etWalletAddress.addTextChangedListener(new
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
if (etWalletAddress.length() > 0) {
llRestoreKeys.setVisibility(View.VISIBLE);
etWalletMnemonic.setVisibility(View.INVISIBLE);
etWalletRestoreHeight.setVisibility(View.VISIBLE);
} else {
llRestoreKeys.setVisibility(View.INVISIBLE);
etWalletMnemonic.setVisibility(View.VISIBLE);
if (etWalletMnemonic.length() == 0) {
etWalletRestoreHeight.setVisibility(View.INVISIBLE);
} else {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
etWalletViewKey.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
etWalletViewKey.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 (viewKeyOk()) {
@ -237,21 +250,22 @@ public class GenerateFragment extends Fragment {
return false;
}
});
etWalletViewKey.setOnClickListener(new View.OnClickListener() {
etWalletViewKey.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Helper.showKeyboard(getActivity());
}
});
etWalletSpendKey.setOnEditorActionListener(new TextView.OnEditorActionListener() {
etWalletSpendKey.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 (spendKeyOk()) {
if (bGenerate.getVisibility() == View.VISIBLE) {
Helper.hideKeyboard(getActivity());
generateWallet();
}
etWalletRestoreHeight.requestFocus();
} else {
Toast.makeText(getActivity(), getString(R.string.generate_check_key), Toast.LENGTH_LONG).show();
}
@ -260,14 +274,18 @@ public class GenerateFragment extends Fragment {
return false;
}
});
etWalletSpendKey.setOnClickListener(new View.OnClickListener() {
etWalletSpendKey.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Helper.showKeyboard(getActivity());
}
});
etWalletRestoreHeight.setOnEditorActionListener(new TextView.OnEditorActionListener() {
etWalletRestoreHeight.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 (bGenerate.getVisibility() == View.VISIBLE) {
@ -280,7 +298,9 @@ public class GenerateFragment extends Fragment {
}
});
bGenerate.setOnClickListener(new View.OnClickListener() {
bGenerate.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
Helper.hideKeyboard(getActivity());

View File

@ -27,8 +27,6 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.model.WalletManager;
// TODO: somehow show which net we are generating for
public class GenerateReviewFragment extends Fragment {
static final String TAG = "GenerateReviewFragment";
@ -84,13 +82,17 @@ public class GenerateReviewFragment extends Fragment {
String seed = b.getString("seed");
String view = b.getString("viewkey");
String spend = b.getString("spendkey");
long height = b.getLong("restoreHeight");
tvWalletName.setText(name);
tvWalletPassword.setText(password);
tvWalletAddress.setText(address);
tvWalletMnemonic.setText(seed);
tvWalletViewKey.setText(view);
tvWalletSpendKey.setText(spend);
if (spend.length() > 0) { // should be == 64, but spendkey is not in the API yet
tvWalletSpendKey.setText(spend);
} else {
tvWalletSpendKey.setText(getString(R.string.generate_wallet_watchonly));
}
bAccept.setEnabled(true);
}

View File

@ -27,6 +27,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
@ -44,6 +45,10 @@ import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import com.m2049r.xmrwallet.util.Helper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
public class LoginActivity extends AppCompatActivity
implements LoginFragment.Listener, GenerateFragment.Listener, GenerateReviewFragment.Listener {
@ -288,8 +293,7 @@ public class LoginActivity extends AppCompatActivity
final String seed = newWallet.getSeed();
final String address = newWallet.getAddress();
final String view = newWallet.getSecretViewKey();
final long height = newWallet.getBlockChainHeight();
final String spend = "not available - use seed for recovery"; //TODO
final String spend = newWallet.isWatchOnly() ? "" : "not available - use seed for recovery";
newWallet.close();
Log.d(TAG, "Created " + address);
runOnUiThread(new Runnable() {
@ -301,7 +305,6 @@ public class LoginActivity extends AppCompatActivity
b.putString("address", address);
b.putString("viewkey", view);
b.putString("spendkey", spend);
b.putLong("restoreHeight", height);
startReviewFragment(b);
}
});
@ -321,7 +324,6 @@ public class LoginActivity extends AppCompatActivity
public Wallet createWallet(String path, String password) {
return WalletManager.getInstance()
.createWallet(path, password, MNEMONIC_LANGUAGE);
}
});
}
@ -358,37 +360,16 @@ public class LoginActivity extends AppCompatActivity
@Override
public void onAccept(final String name, final String password) {
File newWalletFolder = new File(getStorageRoot(), ".new");
if (!newWalletFolder.isDirectory()) {
Log.e(TAG, "New wallet dir " + newWalletFolder.getAbsolutePath() + "is not a directory");
return;
}
final String newWalletPath = new File(newWalletFolder, name).getAbsolutePath();
final File newWalletFolder = new File(getStorageRoot(), ".new");
final File walletFolder = getStorageRoot();
new Thread(null,
new Runnable() {
@Override
public void run() {
Log.d(TAG, "opening wallet " + newWalletPath);
Wallet newWallet = WalletManager.getInstance()
.openWallet(newWalletPath, password);
Wallet.Status status = newWallet.getStatus();
Log.d(TAG, "wallet opened " + newWallet.getStatus());
if (status != Wallet.Status.Status_Ok) {
Log.e(TAG, "New wallet is " + status.toString());
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.generate_wallet_create_failed_1), Toast.LENGTH_LONG).show();
}
});
newWallet.close();
return;
}
final String walletPath = new File(getStorageRoot(), name).getAbsolutePath();
final boolean rc = newWallet.store(walletPath);
Log.d(TAG, "wallet stored with rc=" + rc);
newWallet.close();
Log.d(TAG, "wallet closed");
final String walletPath = new File(walletFolder, name).getAbsolutePath();
final boolean rc = copyWallet(walletFolder, newWalletFolder, name)
&&
(testWallet(walletPath, password) == Wallet.Status.Status_Ok);
runOnUiThread(new Runnable() {
public void run() {
if (rc) {
@ -408,4 +389,45 @@ public class LoginActivity extends AppCompatActivity
, "AcceptWallet", MoneroHandlerThread.THREAD_STACK_SIZE).start();
}
Wallet.Status testWallet(String path, String password) {
Log.d(TAG, "testing wallet " + path);
Wallet aWallet = WalletManager.getInstance().openWallet(path, password);
if (aWallet == null) return Wallet.Status.Status_Error; // does this ever happen?
Wallet.Status status = aWallet.getStatus();
Log.d(TAG, "wallet tested " + aWallet.getStatus());
aWallet.close();
return status;
}
boolean copyWallet(File dstDir, File srcDir, String name) {
boolean success = false;
try {
// TODO: the cache is corrupt if we recover (!!)
// TODO recoveryheight is ignored but not on watchonly wallet ?! - find out why
//copyFile(dstDir, srcDir, name);
copyFile(dstDir, srcDir, name + ".keys");
copyFile(dstDir, srcDir, name + ".address.txt");
success = true;
} catch (IOException ex) {
Log.e(TAG, "wallet copy failed: " + ex.getMessage());
// try to rollback
new File(dstDir, name).delete();
new File(dstDir, name + ".keys").delete();
new File(dstDir, name + ".address.txt").delete();
}
return success;
}
void copyFile(File dstDir, File srcDir, String name) throws IOException {
FileChannel inChannel = new FileInputStream(new File(srcDir, name)).getChannel();
FileChannel outChannel = new FileOutputStream(new File(dstDir, name)).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null)
inChannel.close();
if (outChannel != null)
outChannel.close();
}
}
}

View File

@ -111,7 +111,8 @@ public class WalletService extends Service {
fullRefresh = true;
}
}
observer.onRefreshed(wallet, fullRefresh);
if (observer != null)
observer.onRefreshed(wallet, fullRefresh);
}
}
}
@ -354,6 +355,7 @@ public class WalletService extends Service {
if (listener == null) {
Log.d(TAG, "start() loadWallet");
Wallet aWallet = loadWallet(walletName, walletPassword);
// TODO check aWallet and die gracefully if neccessary
listener = new MyWalletListener(aWallet);
listener.start();
showProgress(100);
@ -420,6 +422,7 @@ public class WalletService extends Service {
wallet = null;
// TODO what do we do with the progress??
// TODO tell the activity this failed
// this crashes in MyWalletListener(Wallet aWallet) as wallet == null
}
}
return wallet;

View File

@ -53,6 +53,8 @@
<string name="generate_button_accept">I have noted the mnemonic seed\nNow, I want to loose all my money!</string>
<string name="generate_button_reset">I\'m confused - Let me start again!</string>
<string name="generate_wallet_watchonly">&lt;Watch Only Wallet&gt;</string>
<string name="generate_wallet_exists">Wallet exists! Choose another name</string>
<string name="generate_wallet_created">Wallet created</string>
<string name="generate_wallet_create_failed_1">Wallet create failed (1/2)</string>