mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-13 16:10:51 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
61e2d880c2 | ||
![]() |
72889fcdde | ||
![]() |
905ee8b8a9 | ||
![]() |
81a9aa6938 | ||
![]() |
046238a29f | ||
![]() |
9751825ed7 | ||
![]() |
c19ee65dd1 | ||
![]() |
282f00959d | ||
![]() |
104a6063a3 | ||
![]() |
95e47e3407 | ||
![]() |
cb5795e64b | ||
![]() |
746da913f0 | ||
![]() |
2682399600 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.gradle
|
||||
build
|
1
.idea/.gitignore
generated
vendored
Normal file
1
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
workspace.xml
|
3068
.idea/workspace.xml
generated
3068
.idea/workspace.xml
generated
File diff suppressed because it is too large
Load Diff
40
README.md
40
README.md
@@ -10,42 +10,40 @@ Another Android Monero Wallet
|
||||
### Disclaimer
|
||||
This is my first serious Android App.
|
||||
|
||||
### Notes
|
||||
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
|
||||
- Special thanks to /u/gkruja for inspiration to pick this project up again
|
||||
- Based off monero v0.10.3.1 with pull requests #2238 & #2239 applied => so can be used in mainnet!
|
||||
### Random Notes
|
||||
- Based off monero v0.10.3.1 with pull requests #2238, #2239 and #2289 applied => so can be used in mainnet!
|
||||
- currently only android32
|
||||
- sorry for my messups in github
|
||||
- this is more of a proof of concept
|
||||
- currently only use is checking incoming/outgoing transactions
|
||||
- currently only use is checking incoming/outgoing transactions
|
||||
- works in testnet & mainnet (please use your own daemons)
|
||||
- takes forever to sync on mainnet (even with own daemon)
|
||||
- takes forever to sync on mainnet (even with own daemon) - 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
|
||||
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
|
||||
|
||||
### TODO
|
||||
- don't have the screen on for first sync - use IntentService with WakeLock instead?
|
||||
- make it pretty
|
||||
- show current block height - is that relevant?
|
||||
- License Dialog
|
||||
- support for right-to-left layouts
|
||||
- visibility of methods/classes
|
||||
- adjust layout so we can use bigger font sizes
|
||||
- adjust layout so we can use bigger font sizes (maybe show only 5 decimal places instead of 12 in main view)
|
||||
- review visibility of methods/classes
|
||||
- sensible error dialogs (e.g. when no write permissions granted) instead of just crashing on purpose
|
||||
- sensible loading/saving progress bars instead of just freezing up
|
||||
- spend monero - not so difficult with wallet api
|
||||
- figure out how to make it all flow better (loading/saving takes forever and does not run in background)
|
||||
- currently loading in background thread produces segfaults in JNI
|
||||
- check licenses of included libraries
|
||||
- check licenses of included libraries; License Dialog
|
||||
- ~~provide detailed build instructions for third party binaries~~
|
||||
- ~~sensible loading/saving progress bars instead of just freezing up~~
|
||||
- ~~figure out how to make it all flow better (loading/saving takes forever and does not run in background)~~
|
||||
- ~~currently loading in background thread produces segfaults in JNI~~
|
||||
|
||||
### Issues
|
||||
- occasional crashes ...
|
||||
- ~~screen rotation crashes the app~~
|
||||
- ~~turning the display off/on during sync stops sync~~
|
||||
|
||||
### HOW TO BUILD
|
||||
No need to build. Binaries are included:
|
||||
|
||||
- openssl-1.0.2l
|
||||
- monero-v0.10.3.1 + pull requests #2238 & #2239
|
||||
- monero-v0.10.3.1 + pull requests #2238, #2239 and #2289
|
||||
- boost_1_64_0
|
||||
|
||||
If you want to build - fire up Android Studio and build. Also you can rebuild all of the above.
|
||||
If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md)
|
||||
|
||||
Then, fire up Android Studio and build the APK.
|
||||
|
2
app/.gitignore
vendored
Normal file
2
app/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.externalNativeBuild
|
||||
build
|
@@ -11,13 +11,13 @@ set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../external-libs)
|
||||
# OpenSSL
|
||||
############
|
||||
|
||||
add_library(crypto SHARED IMPORTED)
|
||||
add_library(crypto STATIC IMPORTED)
|
||||
set_target_properties(crypto PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libcrypto.so)
|
||||
${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libcrypto.a)
|
||||
|
||||
add_library(ssl SHARED IMPORTED)
|
||||
add_library(ssl STATIC IMPORTED)
|
||||
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libssl.so)
|
||||
${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libssl.a)
|
||||
|
||||
############
|
||||
# Boost
|
||||
@@ -63,55 +63,55 @@ set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION
|
||||
# Monero set(libs_to_merge wallet cryptonote_core cryptonote_basic mnemonics common cncrypto ringct)
|
||||
#############
|
||||
|
||||
add_library(wallet SHARED IMPORTED)
|
||||
add_library(wallet STATIC IMPORTED)
|
||||
set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet.a)
|
||||
|
||||
add_library(cryptonote_core SHARED IMPORTED)
|
||||
add_library(cryptonote_core STATIC IMPORTED)
|
||||
set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcryptonote_core.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcryptonote_core.a)
|
||||
|
||||
add_library(cryptonote_basic SHARED IMPORTED)
|
||||
add_library(cryptonote_basic STATIC IMPORTED)
|
||||
set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcryptonote_basic.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcryptonote_basic.a)
|
||||
|
||||
add_library(mnemonics SHARED IMPORTED)
|
||||
add_library(mnemonics STATIC IMPORTED)
|
||||
set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmnemonics.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmnemonics.a)
|
||||
|
||||
add_library(common SHARED IMPORTED)
|
||||
add_library(common STATIC IMPORTED)
|
||||
set_target_properties(common PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcommon.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcommon.a)
|
||||
|
||||
add_library(cncrypto SHARED IMPORTED)
|
||||
add_library(cncrypto STATIC IMPORTED)
|
||||
set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcncrypto.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcncrypto.a)
|
||||
|
||||
add_library(ringct SHARED IMPORTED)
|
||||
add_library(ringct STATIC IMPORTED)
|
||||
set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct.a)
|
||||
|
||||
#####
|
||||
|
||||
add_library(p2p SHARED IMPORTED)
|
||||
add_library(p2p STATIC IMPORTED)
|
||||
set_target_properties(p2p PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libp2p.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libp2p.a)
|
||||
|
||||
add_library(blockchain_db SHARED IMPORTED)
|
||||
add_library(blockchain_db STATIC IMPORTED)
|
||||
set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblockchain_db.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblockchain_db.a)
|
||||
|
||||
add_library(lmdb SHARED IMPORTED)
|
||||
add_library(lmdb STATIC IMPORTED)
|
||||
set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/liblmdb.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/liblmdb.a)
|
||||
|
||||
add_library(easylogging SHARED IMPORTED)
|
||||
add_library(easylogging STATIC IMPORTED)
|
||||
set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libeasylogging.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libeasylogging.a)
|
||||
|
||||
add_library(unbound SHARED IMPORTED)
|
||||
add_library(unbound STATIC IMPORTED)
|
||||
set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libunbound.so)
|
||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libunbound.a)
|
||||
|
||||
####
|
||||
add_library(epee STATIC IMPORTED)
|
||||
@@ -141,9 +141,10 @@ target_link_libraries( monerujo
|
||||
cryptonote_core
|
||||
cryptonote_basic
|
||||
mnemonics
|
||||
cncrypto
|
||||
ringct
|
||||
common
|
||||
cncrypto
|
||||
|
||||
blockchain_db
|
||||
lmdb
|
||||
#easylogging # not for 0.10.3.1
|
||||
|
@@ -92,13 +92,21 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/cmake" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
|
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "0.1"
|
||||
versionCode 3
|
||||
versionName "0.3.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
@@ -17,17 +17,28 @@
|
||||
|
||||
<activity
|
||||
android:name=".WalletActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/wallet_activity_name"
|
||||
android:launchMode="singleTop"></activity>
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"></activity>
|
||||
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:label="@string/app_name">
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="portrait"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".service.WalletService"
|
||||
android:description="@string/service_description"
|
||||
android:exported="false"
|
||||
android:label="Monero Wallet Service" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
@@ -1,3 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "monerujo.h"
|
||||
#include "wallet2_api.h"
|
||||
@@ -336,15 +352,14 @@ Java_com_m2049r_xmrwallet_model_WalletManager_verifyWalletPassword(JNIEnv *env,
|
||||
const char *_keys_file_name = env->GetStringUTFChars(keys_file_name, JNI_FALSE);
|
||||
const char *_password = env->GetStringUTFChars(password, JNI_FALSE);
|
||||
bool passwordOk =
|
||||
Bitmonero::WalletManagerFactory::getWalletManager()->verifyWalletPassword(
|
||||
std::string(_keys_file_name), std::string(_password), watch_only);
|
||||
Bitmonero::WalletManagerFactory::getWalletManager()->verifyWalletPassword(
|
||||
std::string(_keys_file_name), std::string(_password), watch_only);
|
||||
env->ReleaseStringUTFChars(keys_file_name, _keys_file_name);
|
||||
env->ReleaseStringUTFChars(password, _password);
|
||||
return passwordOk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_WalletManager_findWallets(JNIEnv *env, jobject instance,
|
||||
jstring path) {
|
||||
@@ -365,14 +380,15 @@ Java_com_m2049r_xmrwallet_model_WalletManager_getErrorString(JNIEnv *env, jobjec
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_WalletManager_setDaemonAddressJ(JNIEnv *env, jobject instance,
|
||||
jstring address) {
|
||||
jstring address) {
|
||||
const char *_address = env->GetStringUTFChars(address, JNI_FALSE);
|
||||
Bitmonero::WalletManagerFactory::getWalletManager()->setDaemonAddress(std::string(_address));
|
||||
env->ReleaseStringUTFChars(address, _address);
|
||||
}
|
||||
|
||||
// returns whether the daemon can be reached, and its version number
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_WalletManager_getConnectedDaemonVersion(JNIEnv *env,
|
||||
Java_com_m2049r_xmrwallet_model_WalletManager_getDaemonVersion(JNIEnv *env,
|
||||
jobject instance) {
|
||||
uint32_t version;
|
||||
bool isConnected =
|
||||
@@ -449,11 +465,12 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
|
||||
|
||||
// actually a WalletManager function, but logically in Wallet
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_close(JNIEnv *env, jobject instance) {
|
||||
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
||||
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);
|
||||
if (closeSuccess) {
|
||||
MyWalletListener *walletListener = getHandle<MyWalletListener>(env, instance,
|
||||
MyWalletListener *walletListener = getHandle<MyWalletListener>(env, walletInstance,
|
||||
"listenerHandle");
|
||||
if (walletListener != nullptr) {
|
||||
walletListener->deleteGlobalJavaRef(env);
|
||||
@@ -575,9 +592,9 @@ Java_com_m2049r_xmrwallet_model_Wallet_getFilename(JNIEnv *env, jobject instance
|
||||
// virtual std::string keysFilename() const = 0;
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_init(JNIEnv *env, jobject instance,
|
||||
jstring daemon_address,
|
||||
long upper_transaction_size_limit) {
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_initJ(JNIEnv *env, jobject instance,
|
||||
jstring daemon_address,
|
||||
long upper_transaction_size_limit) {
|
||||
// const std::string &daemon_username = "", const std::string &daemon_password = "") = 0;
|
||||
const char *_daemon_address = env->GetStringUTFChars(daemon_address, JNI_FALSE);
|
||||
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
|
||||
|
@@ -1,6 +1,18 @@
|
||||
//
|
||||
// Created by m2049r on 15.04.2017.
|
||||
//
|
||||
/**
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef XMRWALLET_WALLET_LIB_H
|
||||
#define XMRWALLET_WALLET_LIB_H
|
||||
|
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -9,6 +25,7 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
@@ -30,11 +47,19 @@ import com.m2049r.xmrwallet.model.WalletManager;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class LoginActivity extends Activity {
|
||||
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;
|
||||
List<String> walletList = new ArrayList<>();
|
||||
List<String> displayedList = new ArrayList<>();
|
||||
@@ -69,8 +94,12 @@ public class LoginActivity extends Activity {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean mainnet = ((ToggleButton) v).isChecked(); // current state
|
||||
Log.d(TAG, "CLICK NET! mainnet=" + mainnet);
|
||||
savePrefs(true); // use previous state as we just clicked it
|
||||
if (mainnet) {
|
||||
setDaemon(daemonMainNet);
|
||||
} else {
|
||||
setDaemon(daemonTestNet);
|
||||
}
|
||||
filterList();
|
||||
((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
@@ -104,9 +133,17 @@ public class LoginActivity extends Activity {
|
||||
|
||||
final int preambleLength = "[123456] ".length();
|
||||
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;
|
||||
}
|
||||
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);
|
||||
promptPassword(wallet);
|
||||
@@ -180,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) {
|
||||
String walletPath = new File(Helper.getStorageRoot(getApplicationContext()),
|
||||
walletName + ".keys").getAbsolutePath();
|
||||
@@ -187,7 +250,6 @@ public class LoginActivity extends Activity {
|
||||
return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.d(TAG, "onPause()");
|
||||
@@ -195,6 +257,12 @@ public class LoginActivity extends Activity {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Log.d(TAG, "onResume()");
|
||||
}
|
||||
|
||||
boolean isMainNet() {
|
||||
ToggleButton tbMainNet = (ToggleButton) findViewById(R.id.tbMainNet);
|
||||
return tbMainNet.isChecked();
|
||||
@@ -255,20 +323,22 @@ public class LoginActivity extends Activity {
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
void startWallet(String walletName, String walletPassword) {
|
||||
Log.d(TAG, "startWallet()");
|
||||
savePrefs(false);
|
||||
EditText tvDaemonAddress = (EditText) findViewById(R.id.etDaemonAddress);
|
||||
private void setWalletDaemon() {
|
||||
boolean testnet = !isMainNet();
|
||||
Intent intent = new Intent(getApplicationContext(), WalletActivity.class);
|
||||
String daemon = tvDaemonAddress.getText().toString();
|
||||
String daemon = getDaemon();
|
||||
|
||||
if (!daemon.contains(":")) {
|
||||
daemon = daemon + (testnet ? ":28081" : ":18081");
|
||||
}
|
||||
intent.putExtra("daemon", daemon);
|
||||
intent.putExtra("testnet", testnet);
|
||||
intent.putExtra("wallet", walletName);
|
||||
intent.putExtra("password", walletPassword);
|
||||
|
||||
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_PW, walletPassword);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.layout;
|
||||
|
||||
import android.graphics.Color;
|
||||
@@ -22,10 +38,10 @@ import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
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");
|
||||
static final SimpleDateFormat TIME_FORMATTER = new SimpleDateFormat("HH:mm:ss");
|
||||
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
|
||||
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_GREEN = Color.rgb(54, 176, 91);
|
||||
@@ -84,15 +100,15 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
public final TextView tvAmount;
|
||||
public final TextView tvAmountPoint;
|
||||
public final TextView tvAmountDecimal;
|
||||
public final TextView tvDate;
|
||||
public final TextView tvTime;
|
||||
public TransactionInfo infoItem;
|
||||
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
final TextView tvAmount;
|
||||
final TextView tvAmountPoint;
|
||||
final TextView tvAmountDecimal;
|
||||
final TextView tvDate;
|
||||
final TextView tvTime;
|
||||
TransactionInfo infoItem;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
this.tvAmount = (TextView) itemView.findViewById(R.id.tx_amount);
|
||||
// I know this is stupid but can't be bothered to align decimals otherwise
|
||||
|
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
import java.util.List;
|
||||
|
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
public class TransactionInfo {
|
||||
@@ -7,7 +23,7 @@ public class TransactionInfo {
|
||||
|
||||
public long handle;
|
||||
|
||||
public TransactionInfo(long handle) {
|
||||
TransactionInfo(long handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Wallet {
|
||||
static {
|
||||
System.loadLibrary("monerujo");
|
||||
@@ -9,10 +27,15 @@ public class Wallet {
|
||||
|
||||
static final String TAG = "Wallet";
|
||||
|
||||
public String getName() {
|
||||
String p = getPath();
|
||||
return new File(p).getName();
|
||||
}
|
||||
|
||||
private long handle = 0;
|
||||
private long listenerHandle = 0;
|
||||
|
||||
public Wallet(long handle) {
|
||||
Wallet(long handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@@ -30,8 +53,6 @@ public class Wallet {
|
||||
|
||||
//public native long createWalletListenerJ();
|
||||
|
||||
public native boolean close(); // from WalletManager
|
||||
|
||||
public native String getSeed();
|
||||
|
||||
public native String getSeedLanguage();
|
||||
@@ -67,10 +88,19 @@ public class Wallet {
|
||||
|
||||
public native boolean store(String path);
|
||||
|
||||
public boolean close() {
|
||||
return WalletManager.getInstance().close(this);
|
||||
}
|
||||
|
||||
public native String getFilename();
|
||||
|
||||
// virtual std::string keysFilename() const = 0;
|
||||
public native boolean init(String daemon_address, long upper_transaction_size_limit);
|
||||
public boolean init(long upper_transaction_size_limit) {
|
||||
return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit);
|
||||
}
|
||||
|
||||
private native boolean initJ(String daemon_address, long upper_transaction_size_limit);
|
||||
|
||||
// virtual bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const = 0;
|
||||
// virtual void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) = 0;
|
||||
// virtual void setRecoveringFromSeed(bool recoveringFromSeed) = 0;
|
||||
|
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
public interface WalletListener {
|
||||
|
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
import android.util.Log;
|
||||
@@ -8,10 +24,12 @@ import java.io.FileReader;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class WalletManager {
|
||||
final static String TAG = "WalletManager";
|
||||
private final static String TAG = "WalletManager";
|
||||
|
||||
static {
|
||||
System.loadLibrary("monerujo");
|
||||
@@ -27,23 +45,57 @@ public class WalletManager {
|
||||
return WalletManager.Instance;
|
||||
}
|
||||
|
||||
public Wallet createWallet(String path, String password, String language, boolean isTestNet) {
|
||||
long walletHandle = createWalletJ(path, password, language, isTestNet);
|
||||
return new Wallet(walletHandle);
|
||||
private WalletManager() {
|
||||
this.managedWallets = new HashMap<>();
|
||||
}
|
||||
|
||||
public Wallet openWallet(String path, String password, boolean isTestNet) {
|
||||
long walletHandle = openWalletJ(path, password, isTestNet);
|
||||
return new Wallet(walletHandle);
|
||||
private Map<String, Wallet> managedWallets;
|
||||
|
||||
public Wallet getWallet(String walletId) {
|
||||
return managedWallets.get(walletId);
|
||||
}
|
||||
|
||||
public Wallet recoveryWallet(String path, String mnemonic, boolean isTestNet) {
|
||||
return recoveryWallet(path, mnemonic, isTestNet, 0);
|
||||
private void manageWallet(String walletId, Wallet wallet) {
|
||||
if (getWallet(walletId) != null) {
|
||||
throw new IllegalStateException("Wallet already under management!");
|
||||
}
|
||||
Log.d(TAG, "Managing " + walletId);
|
||||
managedWallets.put(walletId, wallet);
|
||||
}
|
||||
|
||||
public Wallet recoveryWallet(String path, String mnemonic, boolean isTestNet, long restoreHeight) {
|
||||
long walletHandle = recoveryWalletJ(path, mnemonic, isTestNet, restoreHeight);
|
||||
return new Wallet(walletHandle);
|
||||
private void unmanageWallet(String walletId) {
|
||||
if (getWallet(walletId) == null) {
|
||||
throw new IllegalStateException("Wallet not under management!");
|
||||
}
|
||||
Log.d(TAG, "Unmanaging " + walletId);
|
||||
managedWallets.remove(walletId);
|
||||
}
|
||||
|
||||
public Wallet createWallet(String path, String password, String language) {
|
||||
long walletHandle = createWalletJ(path, password, language, isTestNet());
|
||||
Wallet wallet = new Wallet(walletHandle);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public Wallet openWallet(String path, String password) {
|
||||
long walletHandle = openWalletJ(path, password, isTestNet());
|
||||
Wallet wallet = new Wallet(walletHandle);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public Wallet recoveryWallet(String path, String mnemonic) {
|
||||
Wallet wallet = recoveryWallet(path, mnemonic, 0);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public Wallet recoveryWallet(String path, String mnemonic, long restoreHeight) {
|
||||
long walletHandle = recoveryWalletJ(path, mnemonic, isTestNet(), restoreHeight);
|
||||
Wallet wallet = new Wallet(walletHandle);
|
||||
manageWallet(wallet.getName(), wallet);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
private native long createWalletJ(String path, String password, String language, boolean isTestNet);
|
||||
@@ -59,6 +111,20 @@ public class WalletManager {
|
||||
String viewKeyString,
|
||||
String spendKeyString);
|
||||
|
||||
public native boolean closeJ(Wallet wallet);
|
||||
|
||||
public boolean close(Wallet wallet) {
|
||||
String walletId = new File(wallet.getFilename()).getName();
|
||||
unmanageWallet(walletId);
|
||||
boolean closed = closeJ(wallet);
|
||||
if (!closed) {
|
||||
// in case we could not close it
|
||||
// we unmanage it
|
||||
manageWallet(walletId, wallet);
|
||||
}
|
||||
return closed;
|
||||
}
|
||||
|
||||
public native boolean walletExists(String path);
|
||||
|
||||
public native boolean verifyWalletPassword(String keys_file_name, String password, boolean watch_only);
|
||||
@@ -85,7 +151,7 @@ public class WalletManager {
|
||||
String filename = found[i].getName();
|
||||
info.name = filename.substring(0, filename.length() - 5); // 5 is length of ".keys"+1
|
||||
File addressFile = new File(path, info.name + ".address.txt");
|
||||
Log.d(TAG, addressFile.getAbsolutePath());
|
||||
//Log.d(TAG, addressFile.getAbsolutePath());
|
||||
info.address = "??????";
|
||||
BufferedReader addressReader = null;
|
||||
try {
|
||||
@@ -111,20 +177,34 @@ public class WalletManager {
|
||||
|
||||
//TODO virtual bool checkPayment(const std::string &address, const std::string &txid, const std::string &txkey, const std::string &daemon_address, uint64_t &received, uint64_t &height, std::string &error) const = 0;
|
||||
|
||||
String daemonAddress = null;
|
||||
private String daemonAddress = null;
|
||||
private boolean testnet = true;
|
||||
|
||||
public void setDaemonAddress(String address) {
|
||||
public boolean isTestNet() {
|
||||
if (daemonAddress == null) {
|
||||
// assume testnet not explicitly initialised
|
||||
throw new IllegalStateException("use setDaemon() to initialise daemon and net first!");
|
||||
}
|
||||
return testnet;
|
||||
}
|
||||
|
||||
public void setDaemon(String address, boolean testnet) {
|
||||
this.daemonAddress = address;
|
||||
this.testnet = testnet;
|
||||
setDaemonAddressJ(address);
|
||||
}
|
||||
|
||||
public String getDaemonAddress() {
|
||||
if (daemonAddress == null) {
|
||||
// assume testnet not explicitly initialised
|
||||
throw new IllegalStateException("use setDaemon() to initialise daemon and net first!");
|
||||
}
|
||||
return this.daemonAddress;
|
||||
}
|
||||
|
||||
private native void setDaemonAddressJ(String address);
|
||||
|
||||
public native int getConnectedDaemonVersion();
|
||||
public native int getDaemonVersion();
|
||||
|
||||
public native long getBlockchainHeight();
|
||||
|
||||
|
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.service;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
|
||||
|
||||
/**
|
||||
* Handy class for starting a new thread that has a looper. The looper can then be
|
||||
* used to create handler classes. Note that start() must still be called.
|
||||
* The started Thread has a stck size of STACK_SIZE (=3MB)
|
||||
*/
|
||||
public class MoneroHandlerThread extends Thread {
|
||||
// from src/cryptonote_config.h
|
||||
static public final long THREAD_STACK_SIZE = 5 * 1024 * 1024;
|
||||
int mPriority;
|
||||
int mTid = -1;
|
||||
Looper mLooper;
|
||||
|
||||
public MoneroHandlerThread(String name) {
|
||||
super(null, null, name, THREAD_STACK_SIZE);
|
||||
mPriority = Process.THREAD_PRIORITY_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MoneroHandlerThread.
|
||||
*
|
||||
* @param name
|
||||
* @param priority The priority to run the thread at. The value supplied must be from
|
||||
* {@link android.os.Process} and not from java.lang.Thread.
|
||||
*/
|
||||
public MoneroHandlerThread(String name, int priority) {
|
||||
super(null, null, name, THREAD_STACK_SIZE);
|
||||
mPriority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call back method that can be explicitly overridden if needed to execute some
|
||||
* setup before Looper loops.
|
||||
*/
|
||||
|
||||
protected void onLooperPrepared() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mTid = Process.myTid();
|
||||
Looper.prepare();
|
||||
synchronized (this) {
|
||||
mLooper = Looper.myLooper();
|
||||
notifyAll();
|
||||
}
|
||||
Process.setThreadPriority(mPriority);
|
||||
onLooperPrepared();
|
||||
Looper.loop();
|
||||
mTid = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Looper associated with this thread. If this thread not been started
|
||||
* or for any reason is isAlive() returns false, this method will return null. If this thread
|
||||
* has been started, this method will block until the looper has been initialized.
|
||||
*
|
||||
* @return The looper.
|
||||
*/
|
||||
public Looper getLooper() {
|
||||
if (!isAlive()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the thread has been started, wait until the looper has been created.
|
||||
synchronized (this) {
|
||||
while (isAlive() && mLooper == null) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return mLooper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quits the handler thread's looper.
|
||||
* <p>
|
||||
* Causes the handler thread's looper to terminate without processing any
|
||||
* more messages in the message queue.
|
||||
* </p><p>
|
||||
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
|
||||
* For example, the {@link Handler#sendMessage(Message)} method will return false.
|
||||
* </p><p class="note">
|
||||
* Using this method may be unsafe because some messages may not be delivered
|
||||
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
|
||||
* that all pending work is completed in an orderly manner.
|
||||
* </p>
|
||||
*
|
||||
* @return True if the looper looper has been asked to quit or false if the
|
||||
* thread had not yet started running.
|
||||
* @see #quitSafely
|
||||
*/
|
||||
public boolean quit() {
|
||||
Looper looper = getLooper();
|
||||
if (looper != null) {
|
||||
looper.quit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quits the handler thread's looper safely.
|
||||
* <p>
|
||||
* Causes the handler thread's looper to terminate as soon as all remaining messages
|
||||
* in the message queue that are already due to be delivered have been handled.
|
||||
* Pending delayed messages with due times in the future will not be delivered.
|
||||
* </p><p>
|
||||
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
|
||||
* For example, the {@link Handler#sendMessage(Message)} method will return false.
|
||||
* </p><p>
|
||||
* If the thread has not been started or has finished (that is if
|
||||
* {@link #getLooper} returns null), then false is returned.
|
||||
* Otherwise the looper is asked to quit and true is returned.
|
||||
* </p>
|
||||
*
|
||||
* @return True if the looper looper has been asked to quit or false if the
|
||||
* thread had not yet started running.
|
||||
*/
|
||||
public boolean quitSafely() {
|
||||
Looper looper = getLooper();
|
||||
if (looper != null) {
|
||||
looper.quitSafely();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of this thread. See Process.myTid().
|
||||
*/
|
||||
public int getThreadId() {
|
||||
return mTid;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.util;
|
||||
|
||||
import android.Manifest;
|
||||
@@ -12,8 +28,8 @@ import com.m2049r.xmrwallet.R;
|
||||
import java.io.File;
|
||||
|
||||
public class Helper {
|
||||
static final String TAG = "Helper";
|
||||
static final String WALLET_DIR = "Monerujo";
|
||||
private static final String TAG = "Helper";
|
||||
private static final String WALLET_DIR = "Monerujo";
|
||||
|
||||
static public File getStorageRoot(Context context) {
|
||||
if (!isExternalStorageWritable()) {
|
||||
@@ -54,11 +70,7 @@ public class Helper {
|
||||
|
||||
static public String getWalletPath(Context context, String aWalletName) {
|
||||
File walletDir = getStorageRoot(context);
|
||||
Log.d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
||||
if (!walletDir.exists()) {
|
||||
Log.d(TAG, "walletdir did not exist!");
|
||||
walletDir.mkdirs();
|
||||
}
|
||||
//d(TAG, "walletdir=" + walletDir.getAbsolutePath());
|
||||
File f = new File(walletDir, aWalletName);
|
||||
Log.d(TAG, "wallet = " + f.getAbsolutePath() + " size=" + f.length());
|
||||
return f.getAbsolutePath();
|
||||
@@ -67,10 +79,7 @@ public class Helper {
|
||||
/* Checks if external storage is available for read and write */
|
||||
static public boolean isExternalStorageWritable() {
|
||||
String state = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.equals(state)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return Environment.MEDIA_MOUNTED.equals(state);
|
||||
}
|
||||
|
||||
}
|
||||
|
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.
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