mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-03 08:23:04 +02:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
49a9f84226 | ||
![]() |
91b4aaad60 | ||
![]() |
c4ce12ceff | ||
![]() |
96cf9ee95e | ||
![]() |
00852da9f7 | ||
![]() |
15b90e7ebc | ||
![]() |
e270b277a5 | ||
![]() |
2842a4042f | ||
![]() |
1614c0ab84 | ||
![]() |
dceca0e198 | ||
![]() |
94947de9ef | ||
![]() |
10ea6d8e0c | ||
![]() |
0d03b75785 | ||
![]() |
a3db07c6a7 | ||
![]() |
6678222202 | ||
![]() |
793d984200 | ||
![]() |
cc46dc06c4 |
1
.idea/.gitignore
generated
vendored
1
.idea/.gitignore
generated
vendored
@@ -1,2 +1,3 @@
|
||||
workspace.xml
|
||||
markdown-*
|
||||
misc.xml
|
||||
|
46
.idea/misc.xml
generated
46
.idea/misc.xml
generated
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
@@ -14,7 +14,7 @@ You may lose all your Moneroj if you use this App. Be cautious when spending on
|
||||
- Based off monero v0.11.0.0 with PR #2289 applied
|
||||
- currently only android32 (runs on 64-bit as well)
|
||||
- works on the testnet & mainnet
|
||||
- takes forever to sync due to 32-bit architecture
|
||||
- sync is slow due to 32-bit architecture
|
||||
- use your own daemon - it's easy
|
||||
- screen stays on until first sync is complete
|
||||
- saves wallet only on first sync and when sending transactions or editing notes
|
||||
@@ -25,11 +25,13 @@ You may lose all your Moneroj if you use this App. Be cautious when spending on
|
||||
- more sensible error dialogs
|
||||
|
||||
### Issues / Pitfalls
|
||||
- The backups folder is now called "backups" and not ".backups" - which in most file explorers was a hidden folder
|
||||
- Wallets are now created directly in the "monerujo" folder, and not in the ".new" folder as before
|
||||
- You may want to check the old folders with a file browsing app and delete the ".new" and ".backups" folders AFTER moving neccessary wallet files to the new locations. Or simply make new backups from within Monerujo.
|
||||
- Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature)
|
||||
- Created wallets on a private testnet are unusable because the restore height is set to that
|
||||
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
|
||||
The official monero client shows the same behaviour.
|
||||
- In rare occasions the monero core code returns a wallet address with corrupted characters -
|
||||
in these cases Monerujo crashes on purpose to make sure nothing bad happens
|
||||
|
||||
### HOW TO BUILD
|
||||
No need to build. Binaries are included:
|
||||
|
@@ -8,8 +8,8 @@ android {
|
||||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 14
|
||||
versionName "0.8.0.1"
|
||||
versionCode 23
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
@@ -3,7 +3,6 @@
|
||||
package="com.m2049r.xmrwallet">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
@@ -39,6 +39,8 @@ static jclass class_WalletListener;
|
||||
static jclass class_TransactionInfo;
|
||||
static jclass class_Transfer;
|
||||
|
||||
std::mutex _listenerMutex;
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
cachedJVM = jvm;
|
||||
LOGI("JNI_OnLoad");
|
||||
@@ -101,6 +103,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
};
|
||||
|
||||
void deleteGlobalJavaRef(JNIEnv *env) {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
env->DeleteGlobalRef(jlistener);
|
||||
jlistener = nullptr;
|
||||
}
|
||||
@@ -109,6 +112,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
* @brief updated - generic callback, called when any event (sent/received/block reveived/etc) happened with the wallet;
|
||||
*/
|
||||
void updated() {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
if (jlistener == nullptr) return;
|
||||
LOGD("updated");
|
||||
JNIEnv *jenv;
|
||||
@@ -128,6 +132,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
* @param amount - amount
|
||||
*/
|
||||
void moneySpent(const std::string &txId, uint64_t amount) {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
if (jlistener == nullptr) return;
|
||||
LOGD("moneySpent %"
|
||||
PRIu64, amount);
|
||||
@@ -139,6 +144,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
* @param amount - amount
|
||||
*/
|
||||
void moneyReceived(const std::string &txId, uint64_t amount) {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
if (jlistener == nullptr) return;
|
||||
LOGD("moneyReceived %"
|
||||
PRIu64, amount);
|
||||
@@ -150,6 +156,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
* @param amount - amount
|
||||
*/
|
||||
void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
if (jlistener == nullptr) return;
|
||||
LOGD("unconfirmedMoneyReceived %"
|
||||
PRIu64, amount);
|
||||
@@ -160,6 +167,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
* @param height - block height
|
||||
*/
|
||||
void newBlock(uint64_t height) {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
if (jlistener == nullptr) return;
|
||||
//LOGD("newBlock");
|
||||
JNIEnv *jenv;
|
||||
@@ -178,6 +186,7 @@ struct MyWalletListener : Bitmonero::WalletListener {
|
||||
* @brief refreshed - called when wallet refreshed by background thread or explicitly refreshed by calling "refresh" synchronously
|
||||
*/
|
||||
void refreshed() {
|
||||
std::lock_guard<std::mutex> lock(_listenerMutex);
|
||||
if (jlistener == nullptr) return;
|
||||
LOGD("refreshed");
|
||||
JNIEnv *jenv;
|
||||
@@ -465,14 +474,15 @@ JNIEXPORT jboolean JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instance,
|
||||
jobject walletInstance) {
|
||||
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, walletInstance);
|
||||
bool closeSuccess = Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(wallet, false);
|
||||
bool closeSuccess = Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(wallet,
|
||||
false);
|
||||
if (closeSuccess) {
|
||||
MyWalletListener *walletListener = getHandle<MyWalletListener>(env, walletInstance,
|
||||
"listenerHandle");
|
||||
if (walletListener != nullptr) {
|
||||
walletListener->deleteGlobalJavaRef(env);
|
||||
delete walletListener;
|
||||
}
|
||||
delete walletListener;
|
||||
}
|
||||
LOGD("wallet closed");
|
||||
return closeSuccess;
|
||||
@@ -531,8 +541,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_setPassword(JNIEnv *env, jobject instance
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_getAddressJ(JNIEnv *env, jobject instance) {
|
||||
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
||||
const char *address = wallet->address().c_str();
|
||||
return env->NewStringUTF(address);
|
||||
return env->NewStringUTF(wallet->address().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
@@ -602,7 +611,8 @@ Java_com_m2049r_xmrwallet_model_Wallet_initJ(JNIEnv *env, jobject instance,
|
||||
const char *_daemon_username = env->GetStringUTFChars(daemon_username, JNI_FALSE);
|
||||
const char *_daemon_password = env->GetStringUTFChars(daemon_password, JNI_FALSE);
|
||||
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
||||
bool status = wallet->init(_daemon_address, upper_transaction_size_limit, _daemon_username, _daemon_password);
|
||||
bool status = wallet->init(_daemon_address, upper_transaction_size_limit, _daemon_username,
|
||||
_daemon_password);
|
||||
env->ReleaseStringUTFChars(daemon_address, _daemon_address);
|
||||
env->ReleaseStringUTFChars(daemon_username, _daemon_username);
|
||||
env->ReleaseStringUTFChars(daemon_password, _daemon_password);
|
||||
@@ -920,7 +930,7 @@ jobject newTransferInstance(JNIEnv *env, uint64_t amount, const std::string &add
|
||||
|
||||
jobject newTransferList(JNIEnv *env, Bitmonero::TransactionInfo *info) {
|
||||
const std::vector<Bitmonero::TransactionInfo::Transfer> &transfers = info->transfers();
|
||||
if (transfers.size()==0) { // don't create empty Lists
|
||||
if (transfers.size() == 0) { // don't create empty Lists
|
||||
return nullptr;
|
||||
}
|
||||
// make new ArrayList
|
||||
|
@@ -18,6 +18,7 @@ package com.m2049r.xmrwallet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
@@ -25,6 +26,8 @@ import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@@ -379,4 +382,15 @@ public class GenerateFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.create_wallet_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
@@ -66,6 +67,20 @@ public class GenerateReviewFragment extends Fragment {
|
||||
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||
tvWalletMnemonic.setTextIsSelectable(testnet);
|
||||
tvWalletSpendKey.setTextIsSelectable(testnet);
|
||||
if (!testnet) {
|
||||
tvWalletMnemonic.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getActivity(), getString(R.string.message_noselect_seed), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
tvWalletSpendKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getActivity(), getString(R.string.message_noselect_key), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bAccept.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@@ -24,6 +24,7 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
@@ -44,15 +45,14 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.m2049r.xmrwallet.layout.DropDownEditText;
|
||||
import com.m2049r.xmrwallet.license.LicensesFragment;
|
||||
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||
import com.m2049r.xmrwallet.dialog.LicensesFragment;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
import com.m2049r.xmrwallet.service.WalletService;
|
||||
import com.m2049r.xmrwallet.util.AsyncExchangeRate;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||
import com.m2049r.xmrwallet.util.NodeList;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -75,13 +75,13 @@ public class LoginActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.d(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.login_activity);
|
||||
setContentView(R.layout.login_activity);
|
||||
if (savedInstanceState != null) {
|
||||
return;
|
||||
// we don't store anything ourselves
|
||||
}
|
||||
|
||||
setContentView(R.layout.login_activity);
|
||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
@@ -308,12 +308,14 @@ public class LoginActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
private boolean backupWallet(String walletName) {
|
||||
File backupFolder = new File(getStorageRoot(), ".backups");
|
||||
File backupFolder = new File(getStorageRoot(), "backups");
|
||||
if (!backupFolder.exists()) {
|
||||
if (!backupFolder.mkdir()) {
|
||||
Log.e(TAG, "Cannot create backup dir " + backupFolder.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
// make folder visible over USB/MTP
|
||||
MediaScannerConnection.scanFile(this, new String[]{backupFolder.toString()}, null, null);
|
||||
}
|
||||
File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
|
||||
File backupFile = new File(backupFolder, walletName);
|
||||
@@ -726,26 +728,17 @@ public class LoginActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
File newWalletFolder = new File(getStorageRoot(), ".new");
|
||||
if (!newWalletFolder.exists()) {
|
||||
if (!newWalletFolder.mkdir()) {
|
||||
Log.e(TAG, "Cannot create new wallet dir " + newWalletFolder.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
File newWalletFolder = getStorageRoot();
|
||||
if (!newWalletFolder.isDirectory()) {
|
||||
Log.e(TAG, "New wallet dir " + newWalletFolder.getAbsolutePath() + "is not a directory");
|
||||
Log.e(TAG, "Wallet dir " + newWalletFolder.getAbsolutePath() + "is not a directory");
|
||||
return false;
|
||||
}
|
||||
File cacheFile = new File(newWalletFolder, walletName);
|
||||
cacheFile.delete();
|
||||
File keysFile = new File(newWalletFolder, walletName + ".keys");
|
||||
keysFile.delete();
|
||||
File addressFile = new File(newWalletFolder, walletName + ".address.txt");
|
||||
addressFile.delete();
|
||||
|
||||
if (cacheFile.exists() || keysFile.exists() || addressFile.exists()) {
|
||||
Log.e(TAG, "Cannot remove all old wallet files: " + cacheFile.getAbsolutePath());
|
||||
Log.e(TAG, "Some wallet files already exist for " + cacheFile.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -854,15 +847,11 @@ public class LoginActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void onAccept(final String name, final String password) {
|
||||
File newWalletFile = new File(new File(getStorageRoot(), ".new"), name);
|
||||
File walletFolder = getStorageRoot();
|
||||
File walletFile = new File(walletFolder, name);
|
||||
boolean rc = copyWallet(newWalletFile, walletFile, false);
|
||||
if (rc) {
|
||||
walletFile.delete(); // when recovering wallets, the cache seems corrupt
|
||||
// TODO: figure out why this is so? Only for a private testnet?
|
||||
rc = testWallet(walletFile.getAbsolutePath(), password) == Wallet.Status.Status_Ok;
|
||||
}
|
||||
walletFile.delete(); // when recovering wallets, the cache seems corrupt
|
||||
// TODO: figure out why this is so? Only for a private testnet?
|
||||
boolean rc = testWallet(walletFile.getAbsolutePath(), password) == Wallet.Status.Status_Ok;
|
||||
|
||||
if (rc) {
|
||||
popFragmentStack(GENERATE_STACK);
|
||||
@@ -871,7 +860,7 @@ public class LoginActivity extends AppCompatActivity
|
||||
} else {
|
||||
Log.e(TAG, "Wallet store failed to " + walletFile.getAbsolutePath());
|
||||
Toast.makeText(LoginActivity.this,
|
||||
getString(R.string.generate_wallet_create_failed_2), Toast.LENGTH_LONG).show();
|
||||
getString(R.string.generate_wallet_create_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,6 +970,9 @@ public class LoginActivity extends AppCompatActivity
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_create_help:
|
||||
HelpFragment.displayHelp(getSupportFragmentManager(),R.raw.help_create);
|
||||
return true;
|
||||
case R.id.action_lincense_info:
|
||||
LicensesFragment.displayLicensesFragment(getSupportFragmentManager());
|
||||
return true;
|
||||
|
@@ -186,7 +186,7 @@ public class LoginFragment extends Fragment {
|
||||
etDaemonAddress.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
if (hasFocus && !getActivity().isFinishing() && etDaemonAddress.isLaidOut()) {
|
||||
etDaemonAddress.showDropDown();
|
||||
Helper.showKeyboard(getActivity());
|
||||
}
|
||||
@@ -376,7 +376,7 @@ public class LoginFragment extends Fragment {
|
||||
}
|
||||
|
||||
String getDaemon() {
|
||||
return etDaemonAddress.getText().toString();
|
||||
return etDaemonAddress.getText().toString().trim();
|
||||
}
|
||||
|
||||
void setDaemon(NodeList nodeList) {
|
||||
|
@@ -150,14 +150,16 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.d(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.wallet_activity);
|
||||
if (savedInstanceState != null) {
|
||||
return;
|
||||
// we don't store anything ourselves
|
||||
}
|
||||
|
||||
setContentView(R.layout.wallet_activity);
|
||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
toolbar.setTitle(R.string.app_name);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
toolbar.setTitle(R.string.app_name);
|
||||
|
||||
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||
if (testnet) {
|
||||
toolbar.setBackgroundResource(R.color.colorPrimaryDark);
|
||||
|
160
app/src/main/java/com/m2049r/xmrwallet/dialog/HelpFragment.java
Normal file
160
app/src/main/java/com/m2049r/xmrwallet/dialog/HelpFragment.java
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Copyright 2013 Adam Speakman, m2049r
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.m2049r.xmrwallet.R;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Based on LicensesFragment by Adam Speakman on 24/09/13.
|
||||
* http://speakman.net.nz
|
||||
*/
|
||||
public class HelpFragment extends DialogFragment {
|
||||
private static final String FRAGMENT_TAG = "com.m2049r.xmrwallet.dialog.HelpFragment";
|
||||
private static final String HELP_ID = "HELP_ID";
|
||||
|
||||
private AsyncTask<Void, Void, String> loader;
|
||||
|
||||
public static HelpFragment newInstance(int helpResourceId) {
|
||||
HelpFragment fragment = new HelpFragment();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(HELP_ID, helpResourceId);
|
||||
fragment.setArguments(bundle);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fm A fragment manager instance used to display this LicensesFragment.
|
||||
*/
|
||||
public static void displayHelp(FragmentManager fm, int helpResourceId) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
ft.addToBackStack(null);
|
||||
|
||||
// Create and show the dialog.
|
||||
DialogFragment newFragment = HelpFragment.newInstance(helpResourceId);
|
||||
newFragment.show(ft, FRAGMENT_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
int helpId = 0;
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
helpId = arguments.getInt(HELP_ID);
|
||||
}
|
||||
if (helpId > 0)
|
||||
loadHelp(helpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (loader != null) {
|
||||
loader.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private WebView webView;
|
||||
private ProgressBar progress;
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
View content = LayoutInflater.from(getActivity()).inflate(R.layout.help_fragment, null);
|
||||
webView = (WebView) content.findViewById(R.id.helpFragmentWebView);
|
||||
progress = (ProgressBar) content.findViewById(R.id.helpFragmentProgress);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
||||
builder.setView(content);
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private void loadHelp(final int helpResourceId) {
|
||||
// Load asynchronously in case of a very large file.
|
||||
loader = new AsyncTask<Void, Void, String>() {
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Void... params) {
|
||||
InputStream rawResource = getActivity().getResources().openRawResource(helpResourceId);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(rawResource));
|
||||
|
||||
String line;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
bufferedReader.close();
|
||||
} catch (IOException e) {
|
||||
// TODO You may want to include some logging here.
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String licensesBody) {
|
||||
super.onPostExecute(licensesBody);
|
||||
if (getActivity() == null || isCancelled()) {
|
||||
return;
|
||||
}
|
||||
progress.setVisibility(View.INVISIBLE);
|
||||
webView.setVisibility(View.VISIBLE);
|
||||
webView.loadDataWithBaseURL(null, licensesBody, "text/html", "utf-8", null);
|
||||
loader = null;
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.license;
|
||||
package com.m2049r.xmrwallet.dialog;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@@ -51,8 +51,7 @@ public class LicensesFragment extends DialogFragment {
|
||||
|
||||
private AsyncTask<Void, Void, String> mLicenseLoader;
|
||||
|
||||
private static final String FRAGMENT_TAG = "nz.net.speakman.androidlicensespage.LicensesFragment";
|
||||
private static final String KEY_SHOW_CLOSE_BUTTON = "keyShowCloseButton";
|
||||
private static final String FRAGMENT_TAG = "com.m2049r.xmrwalelt.dialog.LicensesFragment";
|
||||
|
||||
/**
|
||||
* Creates a new instance of LicensesFragment with no Close button.
|
||||
@@ -63,22 +62,6 @@ public class LicensesFragment extends DialogFragment {
|
||||
return new LicensesFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of LicensesFragment with an optional Close button.
|
||||
*
|
||||
* @param showCloseButton Whether to show a Close button at the bottom of the dialog.
|
||||
* @return A new licenses fragment.
|
||||
*/
|
||||
public static LicensesFragment newInstance(boolean showCloseButton) {
|
||||
LicensesFragment fragment = new LicensesFragment();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_SHOW_CLOSE_BUTTON, showCloseButton);
|
||||
fragment.setArguments(bundle);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and displays a licenses fragment with no Close button. Requires
|
||||
* "/res/raw/licenses.html" and "/res/layout/licenses_fragment.xml" to be
|
||||
@@ -99,27 +82,6 @@ public class LicensesFragment extends DialogFragment {
|
||||
newFragment.show(ft, FRAGMENT_TAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and displays a licenses fragment with or without a Close button.
|
||||
* Requires "/res/raw/licenses.html" and "/res/layout/licenses_fragment.xml"
|
||||
* to be present.
|
||||
*
|
||||
* @param fm A fragment manager instance used to display this LicensesFragment.
|
||||
* @param showCloseButton Whether to show a Close button at the bottom of the dialog.
|
||||
*/
|
||||
public static void displayLicensesFragment(FragmentManager fm, boolean showCloseButton) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
ft.addToBackStack(null);
|
||||
|
||||
// Create and show the dialog.
|
||||
DialogFragment newFragment = LicensesFragment.newInstance(showCloseButton);
|
||||
newFragment.show(ft, FRAGMENT_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
@@ -144,26 +106,18 @@ public class LicensesFragment extends DialogFragment {
|
||||
mWebView = (WebView) content.findViewById(R.id.licensesFragmentWebView);
|
||||
mIndeterminateProgress = (ProgressBar) content.findViewById(R.id.licensesFragmentIndeterminateProgress);
|
||||
|
||||
boolean showCloseButton = false;
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
showCloseButton = arguments.getBoolean(KEY_SHOW_CLOSE_BUTTON);
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
TextView text = (TextView) content.findViewById(R.id.text);
|
||||
TextView text = (TextView) content.findViewById(R.id.licensesFragmentText);
|
||||
text.setText(getString(R.string.about_text, versionName, versionCode));
|
||||
|
||||
builder.setView(content);
|
||||
if (showCloseButton) {
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
@@ -50,8 +50,6 @@ public class Wallet {
|
||||
ConnectionStatus_WrongVersion
|
||||
}
|
||||
|
||||
//public native long createWalletListenerJ();
|
||||
|
||||
public native String getSeed();
|
||||
|
||||
public native String getSeedLanguage();
|
||||
@@ -68,11 +66,11 @@ public class Wallet {
|
||||
|
||||
public native boolean setPassword(String password);
|
||||
|
||||
private String address = null;
|
||||
|
||||
public String getAddress() {
|
||||
String address = getAddressJ();
|
||||
if (!Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) {
|
||||
// just die!
|
||||
throw new IllegalStateException("Wallet returned invalid address!");
|
||||
if (address == null) {
|
||||
address = getAddressJ();
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
9
app/src/main/res/drawable/ic_help_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_help_black_24dp.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
|
||||
</vector>
|
@@ -1,107 +1,112 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletName"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="0dp"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/generate_name_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:textAlignment="center" />
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletName"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/generate_name_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletPassword"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/generate_password_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletPassword"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/generate_password_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletMnemonic"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_mnemonic_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletAddress"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_address_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llRestoreKeys"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletViewKey"
|
||||
android:id="@+id/etWalletMnemonic"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_viewkey_hint"
|
||||
android:hint="@string/generate_mnemonic_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletSpendKey"
|
||||
android:id="@+id/etWalletAddress"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_spendkey_hint"
|
||||
android:hint="@string/generate_address_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="center"/>
|
||||
android:textAlignment="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llRestoreKeys"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletViewKey"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_viewkey_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletSpendKey"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_spendkey_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletRestoreHeight"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_restoreheight_hint"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="number"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bGenerate"
|
||||
style="@style/MoneroButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:enabled="false"
|
||||
android:text="@string/generate_buttonGenerate" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etWalletRestoreHeight"
|
||||
style="@style/MoneroEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_restoreheight_hint"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="number"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bGenerate"
|
||||
style="@style/MoneroButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:enabled="false"
|
||||
android:text="@string/generate_buttonGenerate" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
File diff suppressed because it is too large
Load Diff
29
app/src/main/res/layout/help_fragment.xml
Normal file
29
app/src/main/res/layout/help_fragment.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/helpFragmentIcon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
android:padding="8sp"/>
|
||||
|
||||
<WebView
|
||||
android:id="@+id/helpFragmentWebView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/helpFragmentIcon"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/helpFragmentProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true" />
|
||||
|
||||
</RelativeLayout>
|
@@ -6,18 +6,18 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:id="@+id/licensesFragmentIcon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
android:padding="8sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:id="@+id/licensesFragmentText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about_text"
|
||||
android:layout_below="@+id/icon"
|
||||
android:layout_below="@+id/licensesFragmentIcon"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="8sp"/>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
android:id="@+id/licensesFragmentWebView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/text"
|
||||
android:layout_below="@+id/licensesFragmentText"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ProgressBar
|
||||
|
12
app/src/main/res/menu/create_wallet_menu.xml
Normal file
12
app/src/main/res/menu/create_wallet_menu.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_create_help"
|
||||
android:icon="@drawable/ic_help_black_24dp"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/menu_help"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
38
app/src/main/res/raw/help_create.html
Normal file
38
app/src/main/res/raw/help_create.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>body {font-family: sans-serif; font-size: 1em;}</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Create Wallet</h1>
|
||||
A wallet can be created in a number of ways:
|
||||
<ul>
|
||||
<li>New Address</li>
|
||||
<li>Recover from Seed</li>
|
||||
<li>Recover from Keys</li>
|
||||
<li>View Only</li>
|
||||
</ul>
|
||||
In all cases you need to name your wallet and give it a password. The password is used for
|
||||
securing your wallet data on the device. Use a strong password - better a passphrase.
|
||||
|
||||
<h2>New Address</h2>
|
||||
You need a new Monero Address.<br/>
|
||||
No need to enter additional info.
|
||||
|
||||
<h2>Recover from Seed</h2>
|
||||
You already have a Monero Address and want to recover the transactions from the blockchain.<br/>
|
||||
Enter your Seed in the field "Mnemonic Seed". If you know the block number of the first
|
||||
transaction used for this address, enter it in the field "Restore Height" - leaving in blank will
|
||||
scan the <em>entire</em> blockchain for transactions belonging to your address.
|
||||
This takes a <em>long</em> time.
|
||||
|
||||
<h2>Recover from Keys</h2>
|
||||
Instead of recovering from the mnemonic seed, you can recover using your keys.<br/>
|
||||
Enter your Monero Address in the field "Public Address" and fill out "View Key", "Spend Key"
|
||||
and optionally "Restore Height" with the appropriate values.
|
||||
|
||||
<h2>View Only</h2>
|
||||
You just want to monitor incoming transactions to a wallet.<br/>
|
||||
Enter your Monero Address in the field "Public Address" and fill out the "View Key" and
|
||||
optionally "Restore Height" with the appropriate values leaving the "Spend Key" blank.
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
@@ -6,6 +6,7 @@
|
||||
<string name="menu_testnet">Testnet</string>
|
||||
<string name="menu_about">About …</string>
|
||||
|
||||
<string name="menu_help">Help</string>
|
||||
<string name="menu_info">Details</string>
|
||||
<string name="menu_receive">QR Receive</string>
|
||||
<string name="menu_rename">Rename</string>
|
||||
@@ -82,6 +83,9 @@
|
||||
<string name="message_strorage_not_permitted">We really need those External Storage permissions!</string>
|
||||
<string name="message_camera_not_permitted">No camera = No QR scanning!</string>
|
||||
|
||||
<string name="message_noselect_seed">Selecting seed disabled for security reasons!</string>
|
||||
<string name="message_noselect_key">Selecting spend key disabled for security reasons!</string>
|
||||
|
||||
<string name="generate_title">Create Wallet</string>
|
||||
<string name="generate_name_hint">Wallet Name</string>
|
||||
<string name="generate_password_hint">Wallet Password</string>
|
||||
@@ -100,8 +104,6 @@
|
||||
<string name="generate_wallet_creating">Creating wallet</string>
|
||||
<string name="generate_wallet_created">Wallet created</string>
|
||||
<string name="generate_wallet_create_failed">Wallet create failed</string>
|
||||
<string name="generate_wallet_create_failed_1">Wallet create failed (1/2)</string>
|
||||
<string name="generate_wallet_create_failed_2">Wallet create failed (2/2)</string>
|
||||
<string name="generate_address_placeholder">9tDC52GsMjTNt4dpnRCwAF7ekVBkbkgkXGaMKTcSTpBhGpqkPX56jCNRydLq9oGjbbAQBsZhLfgmTKsntmxRd3TaJFYM2f8</string>
|
||||
<string name="generate_viewkey_placeholder">e2b99f4cc3d644774c4b118db05f8aa9967583a01ca4d47058c3860af10bd306</string>
|
||||
<string name="generate_spendkey_placeholder">300a54208ab0a638a8407a12e3de946da76f5a9ded303338452332ec7755210d</string>
|
||||
|
@@ -8,7 +8,7 @@ replacing "32" with "64".
|
||||
## Prepare Ubuntu environment
|
||||
|
||||
```
|
||||
sudo apt-get install build-essential cmake tofrodos
|
||||
sudo apt-get install build-essential cmake tofrodos libtool-bin
|
||||
sudo mkdir /opt/android
|
||||
sudo chown $LOGNAME /opt/android
|
||||
```
|
||||
@@ -70,9 +70,9 @@ ln -s ../../../../openssl/android-21/lib/libcrypto.so
|
||||
## Build Boost
|
||||
```
|
||||
cd /opt/android
|
||||
wget https://sourceforge.net/projects/boost/files/boost/1.64.0/boost_1_64_0.tar.gz/download -O boost_1_64_0.tar.gz
|
||||
tar xfz boost_1_64_0.tar.gz
|
||||
(cd boost_1_64_0; ./bootstrap.sh)
|
||||
wget https://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.gz/download -O boost_1_58_0.tar.gz
|
||||
tar xfz boost_1_58_0.tar.gz
|
||||
(cd boost_1_58_0; ./bootstrap.sh)
|
||||
```
|
||||
The NDK r15c above gives errors about fsetpos and fgetpos not found(!?!), so we "just" comment them out in the include file:
|
||||
`nano /opt/android/tool32/include/c++/4.9.x/cstdio` (`//using ::fgetpos`, `//using ::fsetpos`)
|
||||
@@ -83,21 +83,57 @@ export PATH=/opt/android/tool32/arm-linux-androideabi/bin:/opt/android/tool32/bi
|
||||
./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android32 --stagedir=android32 toolset=clang threading=multi threadapi=pthread target-os=android stage
|
||||
```
|
||||
|
||||
## Build & prepare zeromq
|
||||
Only needed for zeromq versions (>v0.11.0.0).
|
||||
```
|
||||
cd /opt/android
|
||||
wget git clone https://github.com/zeromq/zeromq3-x.git
|
||||
export PATH=/opt/android/tool32/arm-linux-androideabi/bin:/opt/android/tool32/bin:$PATH
|
||||
export OUTPUT_DIR=/opt/android/zeromq
|
||||
./configure --enable-static --disable-shared --host=arm-linux-androideabi --prefix=$OUTPUT_DIR LDFLAGS="-L$OUTPUT_DIR/lib" CPPFLAGS="-isystem /opt/android/tool32/include/c++/4.9.x -fPIC -I$OUTPUT_DIR/include -Wno-error -D__ANDROID_API__=21" LIBS="-lgcc"
|
||||
make
|
||||
make install
|
||||
|
||||
git clone https://github.com/zeromq/cppzmq.git
|
||||
cp cppzmq/*.hpp zeromq/include/
|
||||
```
|
||||
|
||||
## And finally: Build Monero
|
||||
```
|
||||
cd /opt/android
|
||||
git clone https://github.com/monero-project/monero
|
||||
cd monero
|
||||
|
||||
```
|
||||
```
|
||||
# <patch monero code as needed>
|
||||
|
||||
# also, don't abort on warnings (this is only an issue >v0.11.0.0):
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 1f74f59..2c791c0 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -400,7 +400,7 @@ else()
|
||||
set(ARCH_FLAG "-march=${ARCH}")
|
||||
endif()
|
||||
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
|
||||
- if(NOT MINGW)
|
||||
+ if(NOT MINGW AND NOT ANDROID)
|
||||
set(WARNINGS_AS_ERRORS_FLAG "-Werror")
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
```
|
||||
```
|
||||
mkdir -p build/release.android32
|
||||
cd build/release.android32
|
||||
|
||||
# only if not set already set
|
||||
export PATH=/opt/android/tool32/arm-linux-androideabi/bin:/opt/android/tool32/bin:$PATH
|
||||
|
||||
CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_64_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_64_0/android32/lib -D OPENSSL_ROOT_DIR=/opt/android/openssl/android-21 -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true ../..
|
||||
# for zeromq versions (>v0.11.0.0).
|
||||
CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_58_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_58_0/android32/lib -D OPENSSL_ROOT_DIR=/opt/android/openssl/android-21 -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true -D ZMQ_INCLUDE_PATH=/opt/android/zeromq/include -D ZMQ_LIB=/opt/android/zeromq/lib/libzmq.a ../..
|
||||
|
||||
# for pre-zeromq versions (<=v0.11.0.0).
|
||||
CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_58_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_58_0/android32/lib -D OPENSSL_ROOT_DIR=/opt/android/openssl/android-21 -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true ../..
|
||||
|
||||
make
|
||||
|
||||
find . -name '*.a' -exec cp '{}' lib \;
|
||||
|
@@ -27,6 +27,11 @@
|
||||
- Archive (=Backup and delete)
|
||||
- 3 Default nodes + History of last 5 used nodes
|
||||
|
||||
## After installing from Google Play the wallet list is empty!
|
||||
Sorry about that. The folder for the wallets was renamed from "Monerujo" to "monerujo".
|
||||
On most devices this does not matter (they don't care about upper/lower case). Yours does.
|
||||
If you use a file explorer (e.g. es file explorer) you can find the Monerujo folder and rename it to "monerujo".
|
||||
|
||||
## I cannot select and copy the mnemonic seed
|
||||
Copying anything to the clipboard on Android exposes it to any other App running. So this
|
||||
is a security measure to keep your seed safe(r).
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user