Compare commits
100 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c9927edbd1 | ||
![]() |
f0a3c05a9a | ||
![]() |
d6eb82c457 | ||
![]() |
7f47307307 | ||
![]() |
165dd3dfd1 | ||
![]() |
171727c9db | ||
![]() |
1492814ec9 | ||
![]() |
9b1225fe4b | ||
![]() |
595d88e42e | ||
![]() |
0e207d7401 | ||
![]() |
5920d6c9e8 | ||
![]() |
44fd3c10fa | ||
![]() |
91ab8a681c | ||
![]() |
d843bdb451 | ||
![]() |
2884fc711c | ||
![]() |
8ea2081270 | ||
![]() |
2296329962 | ||
![]() |
fc1bff2160 | ||
![]() |
e61c2b616e | ||
![]() |
ea1e8ac2c3 | ||
![]() |
1082175089 | ||
![]() |
90d64089a6 | ||
![]() |
b689628975 | ||
![]() |
f8e701aa07 | ||
![]() |
d855328c52 | ||
![]() |
bafe05117b | ||
![]() |
4b7c181040 | ||
![]() |
a3721ae784 | ||
![]() |
ae62c528aa | ||
![]() |
e6522769d0 | ||
![]() |
cab93e8c5e | ||
![]() |
ac78ecb298 | ||
![]() |
51876f788f | ||
![]() |
82c32d4442 | ||
![]() |
22b4905828 | ||
![]() |
0cb8ece336 | ||
![]() |
d2429da044 | ||
![]() |
92d867fbaa | ||
![]() |
a5e3986eb9 | ||
![]() |
8f7f4ee9f9 | ||
![]() |
c23597066a | ||
![]() |
dab5e08910 | ||
![]() |
c35deab283 | ||
![]() |
7c36ccfd9c | ||
![]() |
402d51ec6e | ||
![]() |
ca58211676 | ||
![]() |
97c6ba5334 | ||
![]() |
f1f2f250be | ||
![]() |
7b19e9a2bd | ||
![]() |
ed8010c92c | ||
![]() |
41580e5519 | ||
![]() |
1875e2df62 | ||
![]() |
347123d961 | ||
![]() |
f5ad07c2b0 | ||
![]() |
62695af9c6 | ||
![]() |
3b1c3d564b | ||
![]() |
b28a140b48 | ||
![]() |
75bba4a091 | ||
![]() |
cfb3c23003 | ||
![]() |
2cb87bab8e | ||
![]() |
1ddc3d6b58 | ||
![]() |
2fa48d7441 | ||
![]() |
545367db90 | ||
![]() |
d67e02cbcb | ||
![]() |
d3beb7ca3f | ||
![]() |
f951e1a621 | ||
![]() |
0e187d3b20 | ||
![]() |
716b830b7b | ||
![]() |
4ac6a03d63 | ||
![]() |
7eb86ea618 | ||
![]() |
4cfd166ed7 | ||
![]() |
44f241f4ee | ||
![]() |
62b77fc987 | ||
![]() |
03c5569f91 | ||
![]() |
7b1e6a89ba | ||
![]() |
ff8a3ee7c8 | ||
![]() |
dcbaa35b57 | ||
![]() |
3466116e2a | ||
![]() |
59e87e2bfe | ||
![]() |
e8b749af3b | ||
![]() |
f282f01edd | ||
![]() |
f16afdbb19 | ||
![]() |
ccacec9d0b | ||
![]() |
9ebacb8528 | ||
![]() |
49a9f84226 | ||
![]() |
91b4aaad60 | ||
![]() |
c4ce12ceff | ||
![]() |
96cf9ee95e | ||
![]() |
00852da9f7 | ||
![]() |
15b90e7ebc | ||
![]() |
e270b277a5 | ||
![]() |
2842a4042f | ||
![]() |
1614c0ab84 | ||
![]() |
dceca0e198 | ||
![]() |
94947de9ef | ||
![]() |
10ea6d8e0c | ||
![]() |
0d03b75785 | ||
![]() |
a3db07c6a7 | ||
![]() |
6678222202 | ||
![]() |
793d984200 |
1
.gitignore
vendored
@@ -7,3 +7,4 @@
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.DS_Store
|
||||
/app/release
|
||||
|
1
.idea/.gitignore
generated
vendored
@@ -1,2 +1,3 @@
|
||||
workspace.xml
|
||||
markdown-*
|
||||
misc.xml
|
||||
|
10
.idea/libraries/constraint_layout_1_0_2.xml
generated
@@ -1,10 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="constraint-layout-1.0.2">
|
||||
<CLASSES>
|
||||
<root url="file://$USER_HOME$/.android/build-cache/983cd9976ef510b2538361561f2ee91f1200f245/output/res" />
|
||||
<root url="jar://$USER_HOME$/.android/build-cache/983cd9976ef510b2538361561f2ee91f1200f245/output/jars/classes.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="constraint-layout-solver-1.0.2">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/m2repository/com/android/support/constraint/constraint-layout-solver/1.0.2/constraint-layout-solver-1.0.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
10
.idea/libraries/core_1_9_8.xml
generated
@@ -1,10 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="core-1.9.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/jars/classes.jar!/" />
|
||||
<root url="file://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/res" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
11
.idea/libraries/core_3_3_0.xml
generated
@@ -1,11 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="core-3.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/73c49077166faa4c3c0059c5f583d1d7bd1475fe/core-3.3.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/39d966e052e28fc7d83793b02e0af97ccf955745/core-3.3.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
10
.idea/libraries/zxing_1_9_8.xml
generated
@@ -1,10 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="zxing-1.9.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/jars/classes.jar!/" />
|
||||
<root url="file://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/res" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
46
.idea/misc.xml
generated
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
14
README.md
@@ -11,31 +11,29 @@ Another Android Monero Wallet
|
||||
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
|
||||
|
||||
### Random Notes
|
||||
- Based off monero v0.11.0.0 with PR #2289 applied
|
||||
- Based off monero v0.11.1.0
|
||||
- currently only android32 (runs on 64-bit as well)
|
||||
- works on the testnet & mainnet
|
||||
- takes forever to sync due to 32-bit architecture
|
||||
- sync is slow due to 32-bit architecture
|
||||
- use your own daemon - it's easy
|
||||
- screen stays on until first sync is complete
|
||||
- saves wallet only on first sync and when sending transactions or editing notes
|
||||
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
|
||||
|
||||
### TODO
|
||||
- review visibility of methods/classes
|
||||
- more sensible error dialogs
|
||||
- see taiga.getmonero.org & issues on github
|
||||
|
||||
### Issues / Pitfalls
|
||||
- You should backup your wallet files in the "monerujo" folder periodically.
|
||||
- Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature)
|
||||
- Created wallets on a private testnet are unusable because the restore height is set to that
|
||||
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
|
||||
The official monero client shows the same behaviour.
|
||||
- In rare occasions the monero core code returns a wallet address with corrupted characters -
|
||||
in these cases Monerujo crashes on purpose to make sure nothing bad happens
|
||||
|
||||
### HOW TO BUILD
|
||||
No need to build. Binaries are included:
|
||||
|
||||
- openssl-1.0.2l
|
||||
- monero-v0.11.0.0 + pull requests #2289
|
||||
- monero-v0.11.1.0
|
||||
- boost_1_64_0
|
||||
|
||||
If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md)
|
||||
|
@@ -3,13 +3,13 @@ apply plugin: 'witness'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
buildToolsVersion '26.0.2'
|
||||
defaultConfig {
|
||||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 15
|
||||
versionName "0.8.0.2"
|
||||
versionCode 70
|
||||
versionName "1.3.10 'Satoshis Dream'"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
@@ -27,6 +27,9 @@ android {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
@@ -43,28 +46,39 @@ dependencies {
|
||||
compile 'com.android.support:cardview-v7:25.4.0'
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||
|
||||
compile "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion"
|
||||
compile "com.jakewharton.timber:timber:$rootProject.ext.timberVersion"
|
||||
|
||||
testCompile "junit:junit:$rootProject.ext.junitVersion"
|
||||
testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
|
||||
testCompile "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"
|
||||
testCompile 'org.json:json:20140107'
|
||||
testCompile 'net.jodah:concurrentunit:0.4.2'
|
||||
}
|
||||
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
||||
'com.android.support:design:3f409bf2019967ffc344cfaf11e52131fac982468a1707aaeb25bf3c52838966',
|
||||
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
||||
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
||||
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
|
||||
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
|
||||
'com.android.support:support-v4:ee44c481a1f4d6978568e223e8125379b52b2ececdd53450e09ebae144bd377d',
|
||||
'com.android.support:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
|
||||
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
|
||||
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
|
||||
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
|
||||
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
||||
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
||||
'com.android.support:animated-vector-drawable:628ab1d56a6ee4cbedf32617af8b2a1fe02964ed0628e8f898cc09ddba6e1835',
|
||||
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
||||
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
||||
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
||||
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
||||
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
||||
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
|
||||
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
|
||||
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
||||
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
||||
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
||||
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
||||
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
|
||||
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
|
||||
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
||||
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
||||
'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4',
|
||||
]
|
||||
}
|
||||
|
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 8.1 KiB |
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 28 KiB |
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 48 KiB |
4
app/src/debug/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">monerujo - Debug</string>
|
||||
</resources>
|
@@ -3,7 +3,6 @@
|
||||
package="com.m2049r.xmrwallet">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
@@ -14,6 +13,7 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:name=".XmrWalletApplication"
|
||||
android:theme="@style/MyMaterialTheme">
|
||||
|
||||
<activity
|
||||
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 245 KiB |
@@ -19,25 +19,36 @@ package com.m2049r.xmrwallet;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class GenerateReviewFragment extends Fragment {
|
||||
static final String TAG = "GenerateReviewFragment";
|
||||
static final public String VIEW_TYPE_DETAILS = "details";
|
||||
static final public String VIEW_TYPE_ACCEPT = "accept";
|
||||
static final public String VIEW_TYPE_WALLET = "wallet";
|
||||
|
||||
ScrollView scrollview;
|
||||
|
||||
ProgressBar pbProgress;
|
||||
TextView tvWalletName;
|
||||
TextView tvWalletPassword;
|
||||
@@ -45,14 +56,18 @@ public class GenerateReviewFragment extends Fragment {
|
||||
TextView tvWalletMnemonic;
|
||||
TextView tvWalletViewKey;
|
||||
TextView tvWalletSpendKey;
|
||||
ImageButton bCopyAddress;
|
||||
LinearLayout llAdvancedInfo;
|
||||
Button bAdvancedInfo;
|
||||
Button bAccept;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View view = inflater.inflate(R.layout.gen_review_fragment, container, false);
|
||||
View view = inflater.inflate(R.layout.fragment_review, container, false);
|
||||
|
||||
scrollview = (ScrollView) view.findViewById(R.id.scrollview);
|
||||
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
||||
tvWalletName = (TextView) view.findViewById(R.id.tvWalletName);
|
||||
tvWalletPassword = (TextView) view.findViewById(R.id.tvWalletPassword);
|
||||
@@ -60,6 +75,9 @@ public class GenerateReviewFragment extends Fragment {
|
||||
tvWalletViewKey = (TextView) view.findViewById(R.id.tvWalletViewKey);
|
||||
tvWalletSpendKey = (TextView) view.findViewById(R.id.tvWalletSpendKey);
|
||||
tvWalletMnemonic = (TextView) view.findViewById(R.id.tvWalletMnemonic);
|
||||
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
||||
bAdvancedInfo = (Button) view.findViewById(R.id.bAdvancedInfo);
|
||||
llAdvancedInfo = (LinearLayout) view.findViewById(R.id.llAdvancedInfo);
|
||||
|
||||
bAccept = (Button) view.findViewById(R.id.bAccept);
|
||||
|
||||
@@ -73,6 +91,25 @@ public class GenerateReviewFragment extends Fragment {
|
||||
acceptWallet();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.bCopyViewKey).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
copyViewKey();
|
||||
}
|
||||
});
|
||||
bCopyAddress.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
copyAddress();
|
||||
}
|
||||
});
|
||||
bCopyAddress.setClickable(false);
|
||||
view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showAdvancedInfo();
|
||||
}
|
||||
});
|
||||
|
||||
showProgress();
|
||||
|
||||
@@ -85,6 +122,31 @@ public class GenerateReviewFragment extends Fragment {
|
||||
return view;
|
||||
}
|
||||
|
||||
void copyViewKey() {
|
||||
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_viewkey), tvWalletViewKey.getText().toString());
|
||||
Toast.makeText(getActivity(), getString(R.string.message_copy_viewkey), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
void copyAddress() {
|
||||
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address), tvWalletAddress.getText().toString());
|
||||
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
void nocopy() {
|
||||
Toast.makeText(getActivity(), getString(R.string.message_nocopy), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
void showAdvancedInfo() {
|
||||
llAdvancedInfo.setVisibility(View.VISIBLE);
|
||||
bAdvancedInfo.setVisibility(View.GONE);
|
||||
scrollview.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
scrollview.fullScroll(ScrollView.FOCUS_DOWN);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String type;
|
||||
|
||||
private void acceptWallet() {
|
||||
@@ -130,7 +192,7 @@ public class GenerateReviewFragment extends Fragment {
|
||||
address = wallet.getAddress();
|
||||
seed = wallet.getSeed();
|
||||
viewKey = wallet.getSecretViewKey();
|
||||
spendKey = isWatchOnly ? getActivity().getString(R.string.watchonly_label) : wallet.getSecretSpendKey();
|
||||
spendKey = isWatchOnly ? getActivity().getString(R.string.label_watchonly) : wallet.getSecretSpendKey();
|
||||
isWatchOnly = wallet.isWatchOnly();
|
||||
if (closeWallet) wallet.close();
|
||||
return true;
|
||||
@@ -139,6 +201,7 @@ public class GenerateReviewFragment extends Fragment {
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
if (!isAdded()) return; // never mind
|
||||
tvWalletName.setText(name);
|
||||
if (result) {
|
||||
if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
|
||||
@@ -150,9 +213,14 @@ public class GenerateReviewFragment extends Fragment {
|
||||
tvWalletMnemonic.setText(seed);
|
||||
tvWalletViewKey.setText(viewKey);
|
||||
tvWalletSpendKey.setText(spendKey);
|
||||
bAdvancedInfo.setVisibility(View.VISIBLE);
|
||||
bCopyAddress.setClickable(true);
|
||||
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
||||
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||
activityCallback.setToolbarButton(
|
||||
GenerateReviewFragment.VIEW_TYPE_ACCEPT.equals(type) ? Toolbar.BUTTON_NONE : Toolbar.BUTTON_BACK);
|
||||
} else {
|
||||
// TODO show proper error message
|
||||
// TODO end the fragment
|
||||
// TODO show proper error message and/or end the fragment?
|
||||
tvWalletAddress.setText(status.toString());
|
||||
tvWalletMnemonic.setText(status.toString());
|
||||
tvWalletViewKey.setText(status.toString());
|
||||
@@ -162,41 +230,70 @@ public class GenerateReviewFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
GenerateReviewFragment.Listener acceptCallback = null;
|
||||
GenerateReviewFragment.ListenerWithWallet walletCallback = null;
|
||||
Listener activityCallback = null;
|
||||
AcceptListener acceptCallback = null;
|
||||
ListenerWithWallet walletCallback = null;
|
||||
|
||||
public interface Listener {
|
||||
void setTitle(String title, String subtitle);
|
||||
|
||||
void setToolbarButton(int type);
|
||||
}
|
||||
|
||||
public interface AcceptListener {
|
||||
void onAccept(String name, String password);
|
||||
}
|
||||
|
||||
public interface ListenerWithWallet {
|
||||
Wallet getWallet();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof GenerateReviewFragment.Listener) {
|
||||
this.acceptCallback = (GenerateReviewFragment.Listener) context;
|
||||
} else if (context instanceof GenerateReviewFragment.ListenerWithWallet) {
|
||||
this.walletCallback = (GenerateReviewFragment.ListenerWithWallet) context;
|
||||
} else {
|
||||
throw new ClassCastException(context.toString()
|
||||
+ " must implement Listener");
|
||||
if (context instanceof Listener) {
|
||||
this.activityCallback = (Listener) context;
|
||||
}
|
||||
if (context instanceof AcceptListener) {
|
||||
this.acceptCallback = (AcceptListener) context;
|
||||
}
|
||||
if (context instanceof ListenerWithWallet) {
|
||||
this.walletCallback = (ListenerWithWallet) context;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Timber.d("onResume()");
|
||||
String name = tvWalletName.getText().toString();
|
||||
if (name.isEmpty()) name = null;
|
||||
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||
activityCallback.setToolbarButton(
|
||||
GenerateReviewFragment.VIEW_TYPE_ACCEPT.equals(type) ? Toolbar.BUTTON_NONE : Toolbar.BUTTON_BACK);
|
||||
}
|
||||
|
||||
public void showProgress() {
|
||||
pbProgress.setIndeterminate(true);
|
||||
pbProgress.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public void hideProgress() {
|
||||
pbProgress.setVisibility(View.INVISIBLE);
|
||||
pbProgress.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
boolean backOk() {
|
||||
return !type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.wallet_details_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface OnBackPressedListener {
|
||||
boolean onBackPressed();
|
||||
}
|
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -28,24 +27,23 @@ import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.Result;
|
||||
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||
|
||||
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
||||
static final String TAG = "ScannerFragment";
|
||||
|
||||
Listener activityCallback;
|
||||
private OnScannedListener onScannedListener;
|
||||
|
||||
public interface Listener {
|
||||
boolean onAddressScanned(String uri);
|
||||
public interface OnScannedListener {
|
||||
boolean onScanned(String qrCode);
|
||||
}
|
||||
|
||||
private ZXingScannerView mScannerView;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
Log.d(TAG, "onCreateView");
|
||||
Timber.d("onCreateView");
|
||||
mScannerView = new ZXingScannerView(getActivity());
|
||||
return mScannerView;
|
||||
}
|
||||
@@ -53,21 +51,15 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Log.d(TAG, "onResume");
|
||||
Timber.d("onResume");
|
||||
mScannerView.setResultHandler(this);
|
||||
mScannerView.startCamera();
|
||||
}
|
||||
|
||||
static final String QR_SCHEME = "monero:";
|
||||
static final String QR_PAYMENTID = "tx_payment_id";
|
||||
static final String QR_AMOUNT = "tx_amount";
|
||||
|
||||
@Override
|
||||
public void handleResult(Result rawResult) {
|
||||
//Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
|
||||
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
||||
(rawResult.getText().startsWith(QR_SCHEME))) {
|
||||
if (activityCallback.onAddressScanned(rawResult.getText())) {
|
||||
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE)) {
|
||||
if (onScannedListener.onScanned(rawResult.getText())) {
|
||||
return;
|
||||
} else {
|
||||
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
||||
@@ -93,7 +85,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
Log.d(TAG, "onPause");
|
||||
Timber.d("onPause");
|
||||
mScannerView.stopCamera();
|
||||
super.onPause();
|
||||
}
|
||||
@@ -101,12 +93,11 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
//Log.d(TAG, "attaching scan");
|
||||
if (context instanceof Listener) {
|
||||
this.activityCallback = (Listener) context;
|
||||
if (context instanceof OnScannedListener) {
|
||||
this.onScannedListener = (OnScannedListener) context;
|
||||
} else {
|
||||
throw new ClassCastException(context.toString()
|
||||
+ " must implement Listener");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
app/src/main/java/com/m2049r/xmrwallet/SecureActivity.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams;
|
||||
|
||||
public abstract class SecureActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// set FLAG_SECURE to prevent screenshots in Release Mode
|
||||
if (!BuildConfig.DEBUG) {
|
||||
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r et al.
|
||||
*
|
||||
* 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.Application;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class XmrWalletApplication extends Application {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(new Timber.DebugTree());
|
||||
}
|
||||
}
|
||||
}
|