1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-06 02:27:11 +02:00

Compare commits

...

50 Commits
v0.5.3 ... v0.7

Author SHA1 Message Date
m2049r
4918f44048 Docs updated for 0.7 and bugfixes (#55)
* docs and version

* wallet failed message moved to UI thread

* display balance in pure white
2017-09-10 20:04:21 +02:00
m2049r
924c3fa260 allow back only if not accepting (#54) 2017-09-10 10:40:13 +02:00
m2049r
eb2b3b5675 use MoneroThreadPoolExecutor for wallet creation (#53) 2017-09-10 09:49:21 +02:00
Benedict
7a9bb22da7 Added more files and directories to gitignore (#47)
* added files and directories to gitignore we don't need to change and push

* correct gitignore level for .idea folder
2017-09-09 22:16:58 +02:00
m2049r
c7e745cbc3 Merge pull request #52 from m2049r/feature_kraken
Add support for USD/EUR on receive
2017-09-09 22:16:02 +02:00
m2049r
654caaed22 Merge branch 'master' into feature_kraken 2017-09-09 22:15:37 +02:00
m2049r
b8c287b763 cleanup 2017-09-09 22:02:17 +02:00
m2049r
5c1fa097a9 show alternative currency (USD/EUR) on receive
uses https://www.kraken.com/help/api#get-ticker-info
2017-09-09 19:31:37 +02:00
m2049r
80531740dd Update strings.xml 2017-09-09 12:24:01 +02:00
m2049r
08a62cabab Bugfix: Display of unconfirmed amount (#51)
* fix unconfirmed display

* fix unconfirmed display
2017-09-09 12:22:24 +02:00
m2049r
cf4d8bdbf0 fix unconfirmed display 2017-09-09 09:34:44 +02:00
m2049r
7b690a5086 fix merge conflict in gradle-witness.jar 2017-09-09 01:11:17 +02:00
m2049r
e8e5be35b3 Merge branch 'master' of https://github.com/m2049r/xmrwallet 2017-09-09 01:02:56 +02:00
Benedict
5dbf84d5d6 verify checksum from dependencies 2017-09-09 01:01:47 +02:00
m2049r
bf64f77b10 Upgrade to monero v0.11.0.0 (#50) 2017-09-09 01:01:28 +02:00
m2049r
9b82023a9f UI facelift (#49) 2017-09-09 01:01:27 +02:00
KeeJef
be54900e1f Making a few small changes to the readme
Added a link to the release page 
corrected a few small spelling and grammatical errors
2017-09-09 01:01:27 +02:00
KeeJef
033032639a Revert "Update README.md"
This reverts commit 466fd3bf26.
2017-09-09 01:01:27 +02:00
KeeJef
ab8567692f Update README.md 2017-09-09 01:01:27 +02:00
m2049r
65894664a1 Upgrade to monero v0.11.0.0 (#50) 2017-09-09 00:37:12 +02:00
m2049r
e8f53a5a2f UI facelift (#49) 2017-09-08 23:59:50 +02:00
Benedict
22e0a225b0 verify checksum from dependencies 2017-09-08 22:14:09 +02:00
m2049r
e769f1a472 Merge pull request #46 from KeeJef/master
Small changes to the readme
2017-09-07 15:44:13 +02:00
KeeJef
b447df9ef9 Making a few small changes to the readme
Added a link to the release page 
corrected a few small spelling and grammatical errors
2017-09-07 14:27:49 +10:00
KeeJef
42f4e4a0e9 Revert "Update README.md"
This reverts commit 466fd3bf26.
2017-09-07 14:17:12 +10:00
KeeJef
466fd3bf26 Update README.md 2017-09-07 14:15:07 +10:00
KeeJef
c9bbe1db3f Merge pull request #1 from m2049r/master
Merging Up to date
2017-09-07 14:08:27 +10:00
m2049r
dec67e0675 Revert "Upgrade to monero v0.11.0.0 (#44)" (#45)
This reverts commit 9cbeaa7942.
2017-09-06 21:14:38 +02:00
m2049r
9cbeaa7942 Upgrade to monero v0.11.0.0 (#44)
and minor changes
2017-09-06 21:03:31 +02:00
m2049r
093e4bda1d Doc & Version update (#43)
* added hint that amount is in XMR

* update FAQ and version
2017-09-04 23:29:48 +02:00
m2049r
4aa7000cb3 added hint that amount is in XMR (#42)
added hint that amount is in XMR when receiving
2017-09-04 23:27:04 +02:00
m2049r
62844192df Merge pull request #41 from m2049r/bugfix_logo
fixed logo svg
2017-09-04 23:21:29 +02:00
m2049r
855b35a6b7 added l in svg path 2017-09-04 22:52:10 +02:00
m2049r
88110b702f Merge pull request #40 from m2049r/bugfix_issue_37
request and respond to permissions marshmallow style
2017-09-04 22:32:30 +02:00
m2049r
0013caa05f request and respond to permissions marshmallow style 2017-09-04 22:30:37 +02:00
m2049r
5b3e92e91a Merge pull request #39 from m2049r/bugfix_issue_36
Use AsyncTask with 5MB stack in lots of places
2017-09-04 20:51:21 +02:00
m2049r
f8ea3cc77f use AsyncTask with 5MB stack in lots of places 2017-09-04 20:43:05 +02:00
m2049r
59ef2a1f8e Merge pull request #33 from KeeJef/master
Clarifying some Strings
2017-09-04 18:26:30 +02:00
m2049r
fae07ed716 Merge pull request #38 from m2049r/feature_rename_wallet
Rename/Backup/Archive Wallet FIles
2017-09-04 07:34:48 +02:00
m2049r
e662d5a9c0 wallet rename + tweaks 2017-09-04 07:26:04 +02:00
m2049r
4b2d52fbe6 wallet archive/backup progress dialogs 2017-09-03 21:29:15 +02:00
m2049r
ec7798cb34 wallet archive/backup 2017-09-03 14:09:27 +02:00
m2049r
20e7d6d065 rename option in wallet list + tweaks 2017-09-03 11:55:42 +02:00
m2049r
89ada5b294 Merge pull request #35 from m2049r/feature_info_alert
Alert before showing wallet details
2017-09-03 09:44:37 +02:00
m2049r
fe80fef36e alert before showing wallet details 2017-09-03 09:43:52 +02:00
m2049r
e8331dda7a Merge pull request #34 from m2049r/feature_qr_receive
QR Code for receiving
2017-09-02 12:56:17 +02:00
m2049r
68abaec6cb tweaks + get address from wallet (and not from file) 2017-09-02 12:51:57 +02:00
m2049r
fe84bae9ed rework options menus 2017-09-02 10:05:50 +02:00
KeeJef
1289a0ada4 Clarifying some Strings
Just for new people i think the amount when sending should indicate that the values are XMR not USD or something
2017-09-02 13:08:09 +10:00
m2049r
93025c5e1b Receive QR code 2017-09-02 00:00:54 +02:00
87 changed files with 2409 additions and 848 deletions

9
.gitignore vendored
View File

@@ -1,2 +1,9 @@
.gradle
build
/build
*.iml
/.idea/libraries
/.idea/workspace.xml
/local.properties
/captures
.externalNativeBuild
.DS_Store

2
.idea/.gitignore generated vendored
View File

@@ -1,2 +1,2 @@
workspace.xml
markdown-navigator*
markdown-*

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="espresso-core-2.2.2">
<CLASSES>
<root url="file://$USER_HOME$/.android/build-cache/d505abdc89cc7d1b938ec3f95e87d4323360fa14/output/res" />
<root url="jar://$USER_HOME$/.android/build-cache/d505abdc89cc7d1b938ec3f95e87d4323360fa14/output/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/espresso/espresso-core/2.2.2/espresso-core-2.2.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="espresso-idling-resource-2.2.2">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/0dcbbeb3c862ffabe5d9f3c1f70b25bfdf6c739e/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/0dcbbeb3c862ffabe5d9f3c1f70b25bfdf6c739e/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/espresso/espresso-idling-resource/2.2.2/espresso-idling-resource-2.2.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="exposed-instrumentation-api-publish-0.5">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/c11e9f250159df473b4fbff8b80f455f0be2e5b5/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/c11e9f250159df473b4fbff8b80f455f0be2e5b5/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/exposed-instrumentation-api-publish/0.5/exposed-instrumentation-api-publish-0.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="hamcrest-core-1.3">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b/hamcrest-core-1.3-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="hamcrest-integration-1.3">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-integration/1.3/5de0c73fef18917cd85d0ab70bb23818685e4dfd/hamcrest-integration-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="hamcrest-library-1.3">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-library/1.3/4785a3c21320980282f9f33d0d1264a69040538f/hamcrest-library-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="javawriter-2.1.1">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.1.1/67ff45d9ae02e583d0f9b3432a5ebbe05c30c966/javawriter-2.1.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="javax.annotation-api-1.2">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.annotation/javax.annotation-api/1.2/479c1e06db31c432330183f5cae684163f186146/javax.annotation-api-1.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="javax.inject-1">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.inject/javax.inject/1/6975da39a7040257bd51d21a231b76c915872d38/javax.inject-1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="jsr305-2.0.1">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/2.0.1/516c03b21d50a644d538de0f0369c620989cd8f0/jsr305-2.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="junit-4.12">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973d150c0dc1fefe998f834810d68f278ea58ec/junit-4.12.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/a6c32b40bf3d76eca54e3c601e5d1470c86fcdfa/junit-4.12-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="rules-0.5">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/8f8d46a3318b85241b55e25415619e9017c0aef1/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/8f8d46a3318b85241b55e25415619e9017c0aef1/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/rules/0.5/rules-0.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,12 +0,0 @@
<component name="libraryTable">
<library name="runner-0.5">
<CLASSES>
<root url="jar://$USER_HOME$/.android/build-cache/a3a29c4e90c979d7576a0a7d8450261e0065a0a8/output/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.android/build-cache/a3a29c4e90c979d7576a0a7d8450261e0065a0a8/output/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/com/android/support/test/runner/0.5/runner-0.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -2,18 +2,18 @@
Another Android Monero Wallet
### QUICKSTART
- Download APK (Release) and install it
- Download the APK for the most current release [here](https://github.com/m2049r/xmrwallet/releases) and install it
- Run the App and select "Generate Wallet" to create a new wallet or recover a wallet
- Advanced users could copy over synced wallet files (all files) onto sdcard in directory Monerujo (created first time App is started)
- see the [FAQ](doc/FAQ.md)
- Advanced users can copy over synced wallet files (all files) onto sdcard in directory Monerujo (created first time App is started)
- See the [FAQ](doc/FAQ.md)
### Disclaimer
You may loose all your Moneroj if you use this App. Be cautious when spending on mainnet.
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
### Random Notes
- Based off monero v0.10.3.1 with pull requests #2238, #2239 and #2289 applied => so can be used in mainnet!
- Based off monero v0.11.0.0 with PR #2289 applied
- currently only android32 (runs on 64-bit as well)
- works in testnet & mainnet
- works on the testnet & mainnet
- takes forever to sync due to 32-bit architecture
- use your own daemon - it's easy
- screen stays on until first sync is complete
@@ -21,13 +21,14 @@ You may loose all your Moneroj if you use this App. Be cautious when spending on
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
### TODO
- wallet backup functions
- review visibility of methods/classes
- more sensible error dialogs
- check licenses of included libraries; License Dialog
### Issues
- Pending incoming transactions disappear after reload (and appear after being mined)
### Issues / Pitfalls
- 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.
### HOW TO BUILD
No need to build. Binaries are included:
@@ -42,4 +43,4 @@ Then, fire up Android Studio and build the APK.
### Donations
- Address: 4AdkPJoxn7JCvAby9szgnt93MSEwdnxdhaASxbTBm6x5dCwmsDep2UYN4FhStDn5i11nsJbpU7oj59ahg8gXb1Mg3viqCuk
- Viewkey: b1aff2a12191723da0afbe75516f94dd8b068215f6e847d8da57aca5f1f98e0c
- Viewkey: b1aff2a12191723da0afbe75516f94dd8b068215f6e847d8da57aca5f1f98e0c

View File

@@ -147,7 +147,7 @@ target_link_libraries( monerujo
blockchain_db
lmdb
#easylogging # not for 0.10.3.1
easylogging
unbound
p2p

View File

@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'witness'
android {
compileSdkVersion 25
@@ -7,8 +8,8 @@ android {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 25
versionCode 10
versionName "0.5.3"
versionCode 12
versionName "0.7"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -35,11 +36,6 @@ android {
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
@@ -47,5 +43,29 @@ dependencies {
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'me.dm7.barcodescanner:zxing:1.9.8'
testCompile 'junit:junit:4.12'
}
dependencyVerification {
verify = [
'com.android.support:design:a3e83064fe99d0a4369f9b46d8bfbe77d0c3022fffdee4be3ac3857b87cc89e3',
'com.android.support:appcompat-v7:ac1ebbc46589195dda3e0b1becfe410bafd75bdf3edd1cd9acf04850f3895830',
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
'com.android.support:transition:36c688825a8c0e6e879e18886de83dc90673322822d5b606ee302f70fb558e16',
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
'com.android.support:support-v4:07d389154bcf73b47e514964df1578136b26cba78257b8a577a3ccb54beff0ae',
'com.android.support:recyclerview-v7:375974a8724e359d97d77fa8522c614f813a3ac4583c1807f154a3f9a054b0a1',
'com.android.support:cardview-v7:defc17032ffa600a82e1c7d96bb574aa5ed64e2b57e28414a245da7d6db0c666',
'com.android.support:animated-vector-drawable:4bc46edf1946b32d518b41416d1734e915e0cbb28021de3b340527419b070691',
'com.android.support:support-vector-drawable:13728f337f36d1c02d52198a6c20724edb447a0875454d829f95cb9eb4aa293b',
'com.android.support:support-fragment:541d6393c1e024453aca2a14f31bea0c7270ff4e2a02783f3528aa426367444d',
'com.android.support:support-media-compat:cbed07d07e0e84fdb4b75712f5fd946229a8af155933c9a92e41db64d00791e0',
'com.android.support:support-core-utils:32fac02eb2c20a77fa3e3bc3ede62392a19613f72b8f8e10f5dfa84bb4c89ea1',
'com.android.support:support-core-ui:6182278a6653e6c111c888963626cbb16f2d0022571cb239760475119e0b92a8',
'com.android.support:support-compat:e02d781268dc60aab6638d8dc20156ea11ca20b962d294b85e6f1e8418cabfa7',
'com.android.support:support-annotations:aedf76962584adfaed2bd3fcaa22406461c4310237fc27e301128edaa2dba2fa',
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
]
}

View File

@@ -11,10 +11,10 @@
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@drawable/ic_monero_32dp"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/MyMaterialTheme">
<activity
android:name=".WalletActivity"

View File

@@ -461,12 +461,11 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj
//TODO static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
// actually a WalletManager function, but logically in onWalletSelected
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);
bool closeSuccess = Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(wallet, false);
if (closeSuccess) {
MyWalletListener *walletListener = getHandle<MyWalletListener>(env, walletInstance,
"listenerHandle");
@@ -564,8 +563,13 @@ Java_com_m2049r_xmrwallet_model_Wallet_getIntegratedAddress(JNIEnv *env, jobject
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getSecretViewKey(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
//return env->NewStringUTF(wallet->secretViewKey().c_str()); // changed in head
return env->NewStringUTF(wallet->privateViewKey().c_str());
return env->NewStringUTF(wallet->secretViewKey().c_str());
}
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getSecretSpendKey(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return env->NewStringUTF(wallet->secretSpendKey().c_str());
}
JNIEXPORT jboolean JNICALL

View File

@@ -69,12 +69,9 @@ public class GenerateFragment extends Fragment {
bGenerate = (Button) view.findViewById(R.id.bGenerate);
etWalletMnemonic.setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletViewKey.setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletSpendKey.setRawInputType(InputType.TYPE_CLASS_TEXT);
boolean testnet = WalletManager.getInstance().isTestNet();
//etWalletMnemonic.setTextIsSelectable(testnet);
etWalletAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etWalletViewKey.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etWalletSpendKey.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
Helper.showKeyboard(getActivity());
etWalletName.addTextChangedListener(new TextWatcher() {
@@ -298,8 +295,12 @@ public class GenerateFragment extends Fragment {
private void generateWallet() {
String name = etWalletName.getText().toString();
if (name.length() == 0) return;
String walletPath = Helper.getWalletPath(getActivity(), name);
if (WalletManager.getInstance().walletExists(walletPath)) {
if (name.charAt(0)=='.') {
Toast.makeText(getActivity(), getString(R.string.generate_wallet_dot), Toast.LENGTH_LONG).show();
etWalletName.requestFocus();
}
File walletFile = Helper.getWalletFile(getActivity(), name);
if (WalletManager.getInstance().walletExists(walletFile)) {
Toast.makeText(getActivity(), getString(R.string.generate_wallet_exists), Toast.LENGTH_LONG).show();
etWalletName.requestFocus();
return;
@@ -348,7 +349,7 @@ public class GenerateFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onPause()");
Log.d(TAG, "onResume()");
activityCallback.setTitle(getString(R.string.generate_title));
}

View File

@@ -17,8 +17,10 @@
package com.m2049r.xmrwallet;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -28,15 +30,13 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import java.io.File;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
public class GenerateReviewFragment extends Fragment {
static final String TAG = "GenerateReviewFragment";
static final public String VIEW_DETAILS = "details";
static final public String VIEW_ACCEPT = "accept";
static final public String VIEW_WALLET = "wallet";
static final public String VIEW_TYPE_DETAILS = "details";
static final public String VIEW_TYPE_ACCEPT = "accept";
static final public String VIEW_TYPE_WALLET = "wallet";
ProgressBar pbProgress;
TextView tvWalletName;
@@ -76,19 +76,17 @@ public class GenerateReviewFragment extends Fragment {
showProgress();
Bundle b = getArguments();
String type = b.getString("type");
if (!type.equals(VIEW_WALLET)) {
String name = b.getString("name");
String password = b.getString("password");
tvWalletName.setText(new File(name).getName());
show(name, password, type);
} else {
show(walletCallback.getWallet(), null, type);
}
Bundle args = getArguments();
String path = args.getString("path");
String password = args.getString("password");
this.type = args.getString("type");
new AsyncShow().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR,
path, password);
return view;
}
String type;
private void acceptWallet() {
String name = tvWalletName.getText().toString();
String password = tvWalletPassword.getText().toString();
@@ -96,40 +94,72 @@ public class GenerateReviewFragment extends Fragment {
acceptCallback.onAccept(name, password);
}
private void show(final String walletPath, final String password, final String type) {
new Thread(null,
new Runnable() {
@Override
public void run() {
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
getActivity().runOnUiThread(new Runnable() {
public void run() {
show(wallet, password, type);
wallet.close();
}
});
}
}
, "DetailsReview", MoneroHandlerThread.THREAD_STACK_SIZE).start();
}
private class AsyncShow extends AsyncTask<String, Void, Boolean> {
String password;
private void show(final Wallet wallet, final String password, final String type) {
if (type.equals(GenerateReviewFragment.VIEW_ACCEPT)) {
tvWalletPassword.setText(password);
bAccept.setVisibility(View.VISIBLE);
bAccept.setEnabled(true);
String name;
String address;
String seed;
String viewKey;
String spendKey;
boolean isWatchOnly;
Wallet.Status status;
@Override
protected Boolean doInBackground(String... params) {
if (params.length != 2) return false;
String walletPath = params[0];
password = params[1];
Wallet wallet;
boolean closeWallet;
if (type.equals(GenerateReviewFragment.VIEW_TYPE_WALLET)) {
wallet = GenerateReviewFragment.this.walletCallback.getWallet();
closeWallet = false;
} else {
wallet = WalletManager.getInstance().openWallet(walletPath, password);
closeWallet = true;
}
name = wallet.getName();
status = wallet.getStatus();
if (status != Wallet.Status.Status_Ok) {
if (closeWallet) wallet.close();
return false;
}
address = wallet.getAddress();
seed = wallet.getSeed();
viewKey = wallet.getSecretViewKey();
spendKey = isWatchOnly ? getActivity().getString(R.string.watchonly_label) : wallet.getSecretSpendKey();
isWatchOnly = wallet.isWatchOnly();
if (closeWallet) wallet.close();
return true;
}
tvWalletName.setText(wallet.getName());
tvWalletAddress.setText(wallet.getAddress());
tvWalletMnemonic.setText(wallet.getSeed());
tvWalletViewKey.setText(wallet.getSecretViewKey());
String spend = wallet.isWatchOnly() ? "" : "not available - use seed for recovery";
if (spend.length() > 0) { //TODO should be == 64, but spendkey is not in the API yet
tvWalletSpendKey.setText(spend);
} else {
tvWalletSpendKey.setText(getString(R.string.generate_wallet_watchonly));
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
tvWalletName.setText(name);
if (result) {
if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
tvWalletPassword.setText(password);
bAccept.setVisibility(View.VISIBLE);
bAccept.setEnabled(true);
}
tvWalletAddress.setText(address);
tvWalletMnemonic.setText(seed);
tvWalletViewKey.setText(viewKey);
tvWalletSpendKey.setText(spendKey);
} else {
// TODO show proper error message
// TODO end the fragment
tvWalletAddress.setText(status.toString());
tvWalletMnemonic.setText(status.toString());
tvWalletViewKey.setText(status.toString());
tvWalletSpendKey.setText(status.toString());
}
hideProgress();
}
hideProgress();
}
GenerateReviewFragment.Listener acceptCallback = null;
@@ -141,6 +171,7 @@ public class GenerateReviewFragment extends Fragment {
public interface ListenerWithWallet {
Wallet getWallet();
}
@Override
@@ -164,4 +195,8 @@ public class GenerateReviewFragment extends Fragment {
public void hideProgress() {
pbProgress.setVisibility(View.INVISIBLE);
}
boolean backOk() {
return !type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.Log;
@@ -82,9 +83,17 @@ public class LoginFragment extends Fragment {
File getStorageRoot();
void onWalletSelected(final String wallet);
void onWalletSelected(String wallet);
void onWalletDetails(final String wallet);
void onWalletDetails(String wallet);
void onWalletReceive(String wallet);
void onWalletRename(String name);
void onWalletBackup(String name);
void onWalletArchive(String walletName);
void onAddWallet();
@@ -117,14 +126,14 @@ public class LoginFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onPause()");
Log.d(TAG, "onResume()");
activityCallback.setTitle(getString(R.string.login_activity_name));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.login_fragment, container, false);
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
@@ -222,31 +231,6 @@ public class LoginFragment extends Fragment {
}
});
/* listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// Difference to opening wallet is that we don't need a daemon set
String itemValue = (String) listView.getItemAtPosition(position);
if (itemValue.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
return true;
}
String wallet = itemValue.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = isMainNet() ? "4" : "9A";
if (x.indexOf(itemValue.charAt(1)) < 0) {
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
return true;
}
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(wallet);
return true;
}
});
*/
loadList();
return view;
}
@@ -255,24 +239,26 @@ public class LoginFragment extends Fragment {
displayedList.clear();
String x = isMainNet() ? "4" : "9A";
for (String s : walletList) {
// Log.d(TAG, "filtering " + s);
if (x.indexOf(s.charAt(1)) >= 0) displayedList.add(s);
}
}
private void loadList() {
public void loadList() {
Log.d(TAG, "loadList()");
WalletManager mgr = WalletManager.getInstance();
List<WalletManager.WalletInfo> walletInfos =
mgr.findWallets(activityCallback.getStorageRoot());
walletList.clear();
for (WalletManager.WalletInfo walletInfo : walletInfos) {
// Log.d(TAG, walletInfo.address);
// ONCE the walletInfo.address was null - because the address.txt was empty
// this was before the wallet generation was in its own therad with huge stack
// TODO: keep an eye on Wallet.getAddress() returning empty
String displayAddress = walletInfo.address;
if (displayAddress.length() == 95) {
if ((displayAddress != null) && displayAddress.length() == 95) {
displayAddress = walletInfo.address.substring(0, 6);
walletList.add("[" + displayAddress + "] " + walletInfo.name);
}
walletList.add("[" + displayAddress + "] " + walletInfo.name);
}
filterList();
((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
@@ -408,32 +394,52 @@ public class LoginFragment extends Fragment {
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
String listItem = (String) listView.getItemAtPosition(info.position);
String name = nameFromListItem(listItem, !isMainNet());
if (name == null) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
}
switch (item.getItemId()) {
case R.id.action_info:
String listItem = (String) listView.getItemAtPosition(info.position);
return showInfo(listItem);
showInfo(name);
break;
case R.id.action_receive:
showReceive(name);
break;
case R.id.action_rename:
activityCallback.onWalletRename(name);
break;
case R.id.action_backup:
activityCallback.onWalletBackup(name);
break;
case R.id.action_archive:
activityCallback.onWalletArchive(name);
break;
default:
return super.onContextItemSelected(item);
}
}
private boolean showInfo(String listItem) {
if (listItem.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
return true;
}
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = isMainNet() ? "4" : "9A";
if (x.indexOf(listItem.charAt(1)) < 0) {
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
return true;
}
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(wallet);
return true;
}
private void showInfo(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletDetails(name);
}
private boolean showReceive(@NonNull String name) {
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
activityCallback.onWalletReceive(name);
return true;
}
private String nameFromListItem(String listItem, boolean testnet) {
String wallet = listItem.substring(WALLETNAME_PREAMBLE_LENGTH);
String x = testnet ? "9A" : "4";
if (x.indexOf(listItem.charAt(1)) < 0) {
return null;
}
return wallet;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -67,9 +67,10 @@ public class SendFragment extends Fragment {
Button bReallySend;
ProgressBar pbProgress;
final static int Mixins[] = {4, 6, 8, 10, 13}; // must match the layout XML
final static int Mixins[] = {4, 7, 12, 25}; // must match the layout XML
final static PendingTransaction.Priority Priorities[] =
{PendingTransaction.Priority.Priority_Low,
{PendingTransaction.Priority.Priority_Default,
PendingTransaction.Priority.Priority_Low,
PendingTransaction.Priority.Priority_Medium,
PendingTransaction.Priority.Priority_High}; // must match the layout XML
@@ -100,8 +101,8 @@ public class SendFragment extends Fragment {
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
etAddress.setRawInputType(InputType.TYPE_CLASS_TEXT);
etPaymentId.setRawInputType(InputType.TYPE_CLASS_TEXT);
etAddress.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etPaymentId.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
Helper.showKeyboard(getActivity());
@@ -209,7 +210,8 @@ public class SendFragment extends Fragment {
bPaymentId.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etPaymentId.setText((activityCallback.generatePaymentId()));
etPaymentId.setText((Wallet.generatePaymentId()));
etPaymentId.setSelection(etPaymentId.getText().length());
}
});
@@ -285,7 +287,7 @@ public class SendFragment extends Fragment {
private boolean paymentIdOk() {
String paymentId = etPaymentId.getText().toString();
return paymentId.isEmpty() || activityCallback.isPaymentIdValid(paymentId);
return paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId);
}
private void prepareSend() {
@@ -358,10 +360,6 @@ public class SendFragment extends Fragment {
void onSend(String notes);
String generatePaymentId();
boolean isPaymentIdValid(String paymentId);
String getWalletAddress();
void onDisposeRequest();
@@ -446,6 +444,7 @@ public class SendFragment extends Fragment {
}
});
builder.setMessage(errorText);
builder.setCancelable(false);
builder.create().show();
}

View File

@@ -16,13 +16,16 @@
package com.m2049r.xmrwallet;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.UrlQuerySanitizer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
@@ -33,8 +36,6 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
@@ -43,17 +44,22 @@ import com.m2049r.xmrwallet.model.TransactionInfo;
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.BarcodeData;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.TxData;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class WalletActivity extends AppCompatActivity implements WalletFragment.Listener,
WalletService.Observer, SendFragment.Listener, TxFragment.Listener,
GenerateReviewFragment.ListenerWithWallet,
ScannerFragment.Listener {
ScannerFragment.Listener, ReceiveFragment.Listener {
private static final String TAG = "WalletActivity";
public static final String REQUEST_ID = "id";
@@ -90,20 +96,21 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
}
private void startWalletService() {
acquireWakeLock();
Bundle extras = getIntent().getExtras();
if (extras != null) {
acquireWakeLock();
String walletId = extras.getString(REQUEST_ID);
String walletPassword = extras.getString(REQUEST_PW);
connectWalletService(walletId, walletPassword);
} else {
throw new IllegalStateException("No extras passed! Panic!");
finish();
//throw new IllegalStateException("No extras passed! Panic!");
}
}
private void stopWalletService() {
releaseWakeLock();
disconnectWalletService();
releaseWakeLock();
}
@Override
@@ -120,11 +127,8 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!haveWallet) return true;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.wallet_menu, menu);
return true;
public boolean hasWallet() {
return haveWallet;
}
@Override
@@ -132,14 +136,16 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
switch (item.getItemId()) {
case R.id.action_info:
onWalletDetails();
break;
return true;
case R.id.action_receive:
onWalletReceive();
return true;
default:
break;
return super.onOptionsItemSelected(item);
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
@@ -561,16 +567,6 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
}
}
@Override
public String generatePaymentId() {
return getWallet().generatePaymentId();
}
@Override
public boolean isPaymentIdValid(String paymentId) {
return Wallet.isPaymentIdValid(paymentId);
}
@Override
public String getWalletAddress() {
return getWallet().getAddress();
@@ -595,12 +591,27 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
}
private void onWalletDetails() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (!(fragment instanceof GenerateReviewFragment)) {
Bundle extras = new Bundle();
extras.putString("type", GenerateReviewFragment.VIEW_WALLET);
replaceFragment(new GenerateReviewFragment(), null, extras);
}
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
Bundle extras = new Bundle();
extras.putString("type", GenerateReviewFragment.VIEW_TYPE_WALLET);
replaceFragment(new GenerateReviewFragment(), null, extras);
break;
case DialogInterface.BUTTON_NEGATIVE:
// do nothing
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.details_alert_message))
.setPositiveButton(getString(R.string.details_alert_yes), dialogClickListener)
.setNegativeButton(getString(R.string.details_alert_no), dialogClickListener)
.show();
}
@Override
@@ -608,13 +619,20 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
getWallet().disposePendingTransaction();
}
private boolean startScanFragment = false;
@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (startScanFragment) {
startScanFragment();
startScanFragment = false;
}
}
private void startScanFragment() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (fragment instanceof SendFragment) {
Bundle extras = new Bundle();
replaceFragment(new ScannerFragment(), null, extras);
}
Bundle extras = new Bundle();
replaceFragment(new ScannerFragment(), null, extras);
}
/// QR scanner callbacks
@@ -702,7 +720,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startScanFragment();
startScanFragment = true;
} else {
String msg = getString(R.string.message_camera_not_permitted);
Log.e(TAG, msg);
@@ -713,4 +731,25 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
}
}
@Override
public void onWalletReceive() {
startReceive(getWalletAddress());
}
void startReceive(String address) {
Log.d(TAG, "startReceive()");
Bundle b = new Bundle();
b.putString("address", address);
startReceiveFragment(b);
}
void startReceiveFragment(Bundle extras) {
replaceFragment(new ReceiveFragment(), null, extras);
Log.d(TAG, "ReceiveFragment placed");
}
@Override
public void onExchange(AsyncExchangeRate.Listener listener, String currencyA, String currencyB) {
new AsyncExchangeRate(listener).execute(currencyA, currencyB);
}
}

View File

@@ -18,12 +18,16 @@ package com.m2049r.xmrwallet;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -45,7 +49,6 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
private NumberFormat formatter = NumberFormat.getInstance();
TextView tvBalance;
LinearLayout llUnconfirmedAmount;
TextView tvUnconfirmedAmount;
TextView tvBlockHeightProgress;
ConstraintLayout clProgress;
@@ -53,6 +56,19 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
ProgressBar pbProgress;
Button bSend;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (activityCallback.hasWallet())
inflater.inflate(R.menu.wallet_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -61,21 +77,17 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
tvProgress = (TextView) view.findViewById(R.id.tvProgress);
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
clProgress = (ConstraintLayout) view.findViewById(R.id.clProgress);
llUnconfirmedAmount = (LinearLayout) view.findViewById(R.id.llUnconfirmedAmount);
tvBalance = (TextView) view.findViewById(R.id.tvBalance);
tvBalance.setText(Helper.getDisplayAmount(0));
tvBalance.setText(getResources().getString(R.string.xmr_balance, Helper.getDisplayAmount(0)));
tvUnconfirmedAmount = (TextView) view.findViewById(R.id.tvUnconfirmedAmount);
tvUnconfirmedAmount.setText(Helper.getDisplayAmount(0));
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, Helper.getDisplayAmount(0)));
tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress);
bSend = (Button) view.findViewById(R.id.bSend);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list);
RecyclerView.ItemDecoration itemDecoration = new
DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(itemDecoration);
this.adapter = new TransactionInfoAdapter(this);
this.adapter = new TransactionInfoAdapter(getActivity(), this);
recyclerView.setAdapter(adapter);
bSend.setOnClickListener(new View.OnClickListener()
@@ -144,10 +156,12 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
public void showProgress() {
clProgress.setVisibility(View.VISIBLE);
tvBlockHeightProgress.setVisibility(View.GONE);
}
public void hideProgress() {
clProgress.setVisibility(View.GONE);
tvBlockHeightProgress.setVisibility(View.VISIBLE);
}
String setActivityTitle(Wallet wallet) {
@@ -156,6 +170,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
if (shortName.length() > 16) {
shortName = shortName.substring(0, 14) + "...";
}
// TODO very very rarely this craches because getAddress returns "" or so ...
// maybe because this runs in the ui thread and not in a 5MB thread
String title = "[" + wallet.getAddress().substring(0, 6) + "] " + shortName;
activityCallback.setTitle(title);
@@ -177,14 +193,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
}
long balance = wallet.getBalance();
long unlockedBalance = wallet.getUnlockedBalance();
tvBalance.setText(Helper.getDisplayAmount(unlockedBalance));
tvUnconfirmedAmount.setText(Helper.getDisplayAmount(balance - unlockedBalance));
// balance cannot be less than unlockedBalance
/*if (balance != unlockedBalance) {
llPendingAmount.setVisibility(View.VISIBLE);
} else {
llPendingAmount.setVisibility(View.INVISIBLE);
}*/
tvBalance.setText(getResources().getString(R.string.xmr_balance, Helper.getDisplayAmount(unlockedBalance)));
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, Helper.getDisplayAmount(balance - unlockedBalance)));
String sync = "";
if (!activityCallback.hasBoundService())
throw new IllegalStateException("WalletService not bound.");
@@ -236,6 +246,10 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O
boolean isWatchOnly();
String getTxKey(String txId);
void onWalletReceive();
boolean hasWallet();
}
@Override

View File

@@ -16,7 +16,9 @@
package com.m2049r.xmrwallet.layout;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
@@ -42,10 +44,15 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
static final int TX_RED = Color.rgb(255, 79, 65);
static final int TX_GREEN = Color.rgb(54, 176, 91);
static final int TX_PENDING = Color.rgb(72, 53, 176);
static final int TX_FAILED = Color.rgb(208, 0, 255);
//static final int TX_RED = Color.rgb(255, 79, 65);
//static final int TX_GREEN = Color.rgb(54, 176, 91);
//static final int TX_PENDING = Color.rgb(72, 53, 176);
//static final int TX_FAILED = Color.rgb(208, 0, 255);
int outboundColour;
int inboundColour;
int pendingColour;
int failedColour;
public interface OnInteractionListener {
void onInteraction(View view, TransactionInfo item);
@@ -54,7 +61,14 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
private final List<TransactionInfo> infoItems;
private final OnInteractionListener listener;
public TransactionInfoAdapter(OnInteractionListener listener) {
Context context;
public TransactionInfoAdapter(Context context, OnInteractionListener listener) {
this.context = context;
inboundColour = ContextCompat.getColor(context, R.color.tx_green);
outboundColour = ContextCompat.getColor(context, R.color.tx_red);
pendingColour = ContextCompat.getColor(context, R.color.tx_pending);
failedColour = ContextCompat.getColor(context, R.color.tx_failed);
this.infoItems = new ArrayList<>();
this.listener = listener;
Calendar cal = Calendar.getInstance();
@@ -109,8 +123,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
final TextView tvAmount;
final TextView tvAmountPoint;
final TextView tvAmountDecimal;
final TextView tvFee;
final TextView tvPaymentId;
final TextView tvDateTime;
TransactionInfo infoItem;
@@ -118,9 +131,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
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
this.tvAmountPoint = (TextView) itemView.findViewById(R.id.tx_amount_point);
this.tvAmountDecimal = (TextView) itemView.findViewById(R.id.tx_amount_decimal);
this.tvFee = (TextView) itemView.findViewById(R.id.tx_fee);
this.tvPaymentId = (TextView) itemView.findViewById(R.id.tx_paymentid);
this.tvDateTime = (TextView) itemView.findViewById(R.id.tx_datetime);
}
@@ -131,34 +142,41 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
private void setTxColour(int clr) {
tvAmount.setTextColor(clr);
tvAmountDecimal.setTextColor(clr);
tvAmountPoint.setTextColor(clr);
tvFee.setTextColor(clr);
}
void bind(int position) {
this.infoItem = infoItems.get(position);
String displayAmount = Wallet.getDisplayAmount(infoItem.amount);
// TODO fix this with i8n code but cryptonote::print_money always uses '.' for decimal point
String amountParts[] = displayAmount.split("\\.");
amountParts[1] = amountParts[1].substring(0,5);
String amount = displayAmount.substring(0, displayAmount.length() - (12 - 5));
this.tvAmount.setText(amount);
this.tvAmount.setText(amountParts[0]);
this.tvAmountDecimal.setText(amountParts[1]);
if ((infoItem.fee > 0)) {
String feeAmount = Wallet.getDisplayAmount(infoItem.fee);
String fee = feeAmount.substring(0, feeAmount.length() - (12 - 5));
if (infoItem.isPending) {
this.tvFee.setText(context.getString(R.string.tx_list_fee_pending, fee));
} else {
this.tvFee.setText(context.getString(R.string.tx_list_fee, fee));
}
} else {
this.tvFee.setText("");
}
if (infoItem.isFailed) {
this.tvAmount.setText('(' + amountParts[0]);
this.tvAmountDecimal.setText(amountParts[1] + ')');
setTxColour(TX_FAILED);
this.tvAmount.setText(context.getString(R.string.tx_list_amount_failed, amount));
setTxColour(failedColour);
} else if (infoItem.isPending) {
setTxColour(TX_PENDING);
setTxColour(pendingColour);
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
this.tvAmount.setText('-' + amountParts[0]);
this.tvAmount.setText(context.getString(R.string.tx_list_amount_negative, amount));
}
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
setTxColour(TX_GREEN);
setTxColour(inboundColour);
} else {
setTxColour(TX_RED);
setTxColour(outboundColour);
}
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000")?"":infoItem.paymentId);
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000") ? "" : infoItem.paymentId);
this.tvDateTime.setText(getDateTime(infoItem.timestamp));
itemView.setOnClickListener(this);

View File

@@ -34,6 +34,7 @@ public class PendingTransaction {
}
public enum Priority {
Priority_Default(0),
Priority_Low(1),
Priority_Medium(2),
Priority_High(3),
@@ -41,6 +42,8 @@ public class PendingTransaction {
public static Priority fromInteger(int n) {
switch (n) {
case 0:
return Priority_Default;
case 1:
return Priority_Low;
case 2:

View File

@@ -81,6 +81,8 @@ public class Wallet {
public native String getSecretViewKey();
public native String getSecretSpendKey();
public boolean store() {
return store("");
}
@@ -238,6 +240,7 @@ public class Wallet {
public native void setDefaultMixin(int mixin);
public native boolean setUserNote(String txid, String note);
public native String getUserNote(String txid);
public native String getTxKey(String txid);

View File

@@ -71,8 +71,8 @@ public class WalletManager {
managedWallets.remove(walletId);
}
public Wallet createWallet(String path, String password, String language) {
long walletHandle = createWalletJ(path, password, language, isTestNet());
public Wallet createWallet(File aFile, String password, String language) {
long walletHandle = createWalletJ(aFile.getAbsolutePath(), password, language, isTestNet());
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet.getName(), wallet);
return wallet;
@@ -89,14 +89,14 @@ public class WalletManager {
private native long openWalletJ(String path, String password, boolean isTestNet);
public Wallet recoveryWallet(String path, String mnemonic) {
Wallet wallet = recoveryWallet(path, mnemonic, 0);
public Wallet recoveryWallet(File aFile, String mnemonic) {
Wallet wallet = recoveryWallet(aFile, mnemonic, 0);
manageWallet(wallet.getName(), wallet);
return wallet;
}
public Wallet recoveryWallet(String path, String mnemonic, long restoreHeight) {
long walletHandle = recoveryWalletJ(path, mnemonic, isTestNet(), restoreHeight);
public Wallet recoveryWallet(File aFile, String mnemonic, long restoreHeight) {
long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), mnemonic, isTestNet(), restoreHeight);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet.getName(), wallet);
return wallet;
@@ -104,9 +104,9 @@ public class WalletManager {
private native long recoveryWalletJ(String path, String mnemonic, boolean isTestNet, long restoreHeight);
public Wallet createWalletFromKeys(String path, String language, long restoreHeight,
public Wallet createWalletFromKeys(File aFile, String language, long restoreHeight,
String addressString, String viewKeyString, String spendKeyString) {
long walletHandle = createWalletFromKeysJ(path, language, isTestNet(), restoreHeight,
long walletHandle = createWalletFromKeysJ(aFile.getAbsolutePath(), language, isTestNet(), restoreHeight,
addressString, viewKeyString, spendKeyString);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet.getName(), wallet);
@@ -134,6 +134,10 @@ public class WalletManager {
return closed;
}
public boolean walletExists(File aFile) {
return walletExists(aFile.getAbsolutePath());
}
public native boolean walletExists(String path);
public native boolean verifyWalletPassword(String keys_file_name, String password, boolean watch_only);
@@ -146,6 +150,31 @@ public class WalletManager {
public String address;
}
public WalletInfo getWalletInfo(File wallet) {
WalletInfo info = new WalletInfo();
info.path = wallet.getParentFile();
info.name = wallet.getName();
File addressFile = new File(info.path, info.name + ".address.txt");
//Log.d(TAG, addressFile.getAbsolutePath());
info.address = "??????";
BufferedReader addressReader = null;
try {
addressReader = new BufferedReader(new FileReader(addressFile));
info.address = addressReader.readLine();
} catch (IOException ex) {
Log.d(TAG, ex.getLocalizedMessage());
} finally {
if (addressReader != null) {
try {
addressReader.close();
} catch (IOException ex) {
// that's just too bad
}
}
}
return info;
}
public List<WalletInfo> findWallets(File path) {
List<WalletInfo> wallets = new ArrayList<>();
Log.d(TAG, "Scanning: " + path.getAbsolutePath());
@@ -155,29 +184,9 @@ public class WalletManager {
}
});
for (int i = 0; i < found.length; i++) {
WalletInfo info = new WalletInfo();
info.path = path;
String filename = found[i].getName();
info.name = filename.substring(0, filename.length() - 5); // 5 is length of ".keys"+1
File addressFile = new File(path, info.name + ".address.txt");
//Log.d(TAG, addressFile.getAbsolutePath());
info.address = "??????";
BufferedReader addressReader = null;
try {
addressReader = new BufferedReader(new FileReader(addressFile));
info.address = addressReader.readLine();
} catch (IOException ex) {
Log.d(TAG, ex.getLocalizedMessage());
} finally {
if (addressReader != null) {
try {
addressReader.close();
} catch (IOException ex) {
// that's just too bad
}
}
}
wallets.add(info);
File f = new File(found[i].getParent(), filename.substring(0, filename.length() - 5)); // 5 is length of ".keys"+1
wallets.add(getWalletInfo(f));
}
return wallets;
}

Some files were not shown because too many files have changed in this diff Show More