mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-04 17:28:42 +02:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
06456e33e4 | ||
![]() |
d97b36aa44 | ||
![]() |
8fa06e5b37 | ||
![]() |
8d95de828b | ||
![]() |
93a7be0452 | ||
![]() |
25c8ec1229 | ||
![]() |
0bf0444dce | ||
![]() |
b74f9c6bd7 | ||
![]() |
f843bb1685 | ||
![]() |
7d9d49c29e |
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 166
|
||||
versionName "1.10.16 'Node-O-matiC'"
|
||||
versionCode 171
|
||||
versionName "1.11.1 'Chernushka'"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
|
@@ -26,14 +26,14 @@
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/wallet_activity_name"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="behind" />
|
||||
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait">
|
||||
android:screenOrientation="locked">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
@@ -68,5 +68,15 @@
|
||||
android:description="@string/service_description"
|
||||
android:exported="false"
|
||||
android:label="Monero Wallet Service" />
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/filepaths" />
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
@@ -60,14 +60,14 @@ enum {
|
||||
HASH_DATA_AREA = 136
|
||||
};
|
||||
|
||||
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed);
|
||||
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height);
|
||||
|
||||
inline void slow_hash(const void *data, const size_t length, char *hash) {
|
||||
cn_slow_hash(data, length, hash, 0 /* variant */, 0/*prehashed*/);
|
||||
cn_slow_hash(data, length, hash, 0 /*variant*/, 0 /*prehashed*/, 0 /*height*/);
|
||||
}
|
||||
|
||||
inline void slow_hash_broken(const void *data, char *hash, int variant) {
|
||||
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, variant, 1 /*prehashed*/);
|
||||
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, variant, 1 /*prehashed*/, 0 /*height*/);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -173,10 +173,10 @@ public class LevinReader {
|
||||
|
||||
// this should be in LittleEndianDataInputStream because it has little
|
||||
// endian logic
|
||||
private long readRest(int firstByte, int bytes) throws IOException {
|
||||
private long readRest(final int firstByte, final int bytes) throws IOException {
|
||||
long result = firstByte;
|
||||
for (int i = 0; i < bytes; i++) {
|
||||
result = result + (in.readUnsignedByte() << 8);
|
||||
for (int i = 1; i < bytes + 1; i++) {
|
||||
result = result + (((long) in.readUnsignedByte()) << (8 * i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -95,7 +95,6 @@ public class GenerateFragment extends Fragment {
|
||||
etWalletRestoreHeight = view.findViewById(R.id.etWalletRestoreHeight);
|
||||
bGenerate = view.findViewById(R.id.bGenerate);
|
||||
|
||||
etWalletMnemonic.getEditText().setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||
etWalletAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
etWalletViewKey.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
etWalletSpendKey.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
|
@@ -17,19 +17,28 @@
|
||||
package com.m2049r.xmrwallet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NfcManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.ShareActionProvider;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
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.view.inputmethod.EditorInfo;
|
||||
@@ -56,6 +65,9 @@ import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||
import com.m2049r.xmrwallet.widget.ExchangeView;
|
||||
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -69,8 +81,8 @@ public class ReceiveFragment extends Fragment {
|
||||
private TextInputLayout etNotes;
|
||||
private ExchangeView evAmount;
|
||||
private TextView tvQrCode;
|
||||
private ImageView qrCode;
|
||||
private ImageView qrCodeFull;
|
||||
private ImageView ivQrCode;
|
||||
private ImageView ivQrCodeFull;
|
||||
private EditText etDummy;
|
||||
private ImageButton bCopyAddress;
|
||||
private Button bSubaddress;
|
||||
@@ -97,9 +109,9 @@ public class ReceiveFragment extends Fragment {
|
||||
tvAddress = view.findViewById(R.id.tvAddress);
|
||||
etNotes = view.findViewById(R.id.etNotes);
|
||||
evAmount = view.findViewById(R.id.evAmount);
|
||||
qrCode = view.findViewById(R.id.qrCode);
|
||||
ivQrCode = view.findViewById(R.id.qrCode);
|
||||
tvQrCode = view.findViewById(R.id.tvQrCode);
|
||||
qrCodeFull = view.findViewById(R.id.qrCodeFull);
|
||||
ivQrCodeFull = view.findViewById(R.id.qrCodeFull);
|
||||
etDummy = view.findViewById(R.id.etDummy);
|
||||
bCopyAddress = view.findViewById(R.id.bCopyAddress);
|
||||
bSubaddress = view.findViewById(R.id.bSubaddress);
|
||||
@@ -178,25 +190,25 @@ public class ReceiveFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
qrCode.setOnClickListener(new View.OnClickListener() {
|
||||
ivQrCode.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Helper.hideKeyboard(getActivity());
|
||||
etDummy.requestFocus();
|
||||
if (qrValid) {
|
||||
qrCodeFull.setImageBitmap(((BitmapDrawable) qrCode.getDrawable()).getBitmap());
|
||||
qrCodeFull.setVisibility(View.VISIBLE);
|
||||
ivQrCodeFull.setImageBitmap(((BitmapDrawable) ivQrCode.getDrawable()).getBitmap());
|
||||
ivQrCodeFull.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
evAmount.doExchange();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
qrCodeFull.setOnClickListener(new View.OnClickListener() {
|
||||
ivQrCodeFull.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
qrCodeFull.setImageBitmap(null);
|
||||
qrCodeFull.setVisibility(View.GONE);
|
||||
ivQrCodeFull.setImageBitmap(null);
|
||||
ivQrCodeFull.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -228,6 +240,81 @@ public class ReceiveFragment extends Fragment {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
private ShareActionProvider shareActionProvider;
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.receive_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
// Locate MenuItem with ShareActionProvider
|
||||
MenuItem item = menu.findItem(R.id.menu_item_share);
|
||||
|
||||
// Fetch and store ShareActionProvider
|
||||
shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);
|
||||
|
||||
shareActionProvider.setOnShareTargetSelectedListener(new ShareActionProvider.OnShareTargetSelectedListener() {
|
||||
@Override
|
||||
public boolean onShareTargetSelected(ShareActionProvider shareActionProvider, Intent intent) {
|
||||
saveQrCode(); // save it only if we need it
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setShareIntent() {
|
||||
if (shareActionProvider != null) {
|
||||
if (qrValid) {
|
||||
shareActionProvider.setShareIntent(getShareIntent());
|
||||
} else {
|
||||
shareActionProvider.setShareIntent(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveQrCode() {
|
||||
if (!qrValid) throw new IllegalStateException("trying to save null qr code!");
|
||||
|
||||
File cachePath = new File(getActivity().getCacheDir(), "images");
|
||||
if (!cachePath.exists())
|
||||
if (!cachePath.mkdirs()) throw new IllegalStateException("cannot create images folder");
|
||||
File png = new File(cachePath, "QR.png");
|
||||
try {
|
||||
FileOutputStream stream = new FileOutputStream(png);
|
||||
Bitmap qrBitmap = ((BitmapDrawable) ivQrCode.getDrawable()).getBitmap();
|
||||
qrBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
stream.close();
|
||||
} catch (IOException ex) {
|
||||
Timber.e(ex);
|
||||
// make sure we don't share an old qr code
|
||||
if (!png.delete()) throw new IllegalStateException("cannot delete old qr code");
|
||||
// if we manage to delete it, the URI points to nothing and the user gets a toast with the error
|
||||
}
|
||||
}
|
||||
|
||||
private Intent getShareIntent() {
|
||||
File imagePath = new File(getActivity().getCacheDir(), "images");
|
||||
File png = new File(imagePath, "QR.png");
|
||||
Uri contentUri = FileProvider.getUriForFile(getActivity(),
|
||||
"com.m2049r.xmrwallet.fileprovider", png);
|
||||
if (contentUri != null) {
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
|
||||
shareIntent.setDataAndType(contentUri, getActivity().getContentResolver().getType(contentUri));
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, bcData.getUriString());
|
||||
return shareIntent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void enableSubaddressButton(boolean enable) {
|
||||
bSubaddress.setEnabled(enable);
|
||||
if (enable) {
|
||||
@@ -242,23 +329,23 @@ public class ReceiveFragment extends Fragment {
|
||||
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
boolean qrValid = true;
|
||||
private boolean qrValid = false;
|
||||
|
||||
void clearQR() {
|
||||
if (qrValid) {
|
||||
qrCode.setImageBitmap(null);
|
||||
ivQrCode.setImageBitmap(null);
|
||||
qrValid = false;
|
||||
setShareIntent();
|
||||
if (isLoaded)
|
||||
tvQrCode.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
void setQR(Bitmap qr) {
|
||||
qrCode.setImageBitmap(qr);
|
||||
ivQrCode.setImageBitmap(qr);
|
||||
qrValid = true;
|
||||
setShareIntent();
|
||||
tvQrCode.setVisibility(View.GONE);
|
||||
Helper.hideKeyboard(getActivity());
|
||||
etDummy.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -392,7 +479,7 @@ public class ReceiveFragment extends Fragment {
|
||||
return;
|
||||
}
|
||||
bcData = new BarcodeData(BarcodeData.Asset.XMR, address, null, notes, xmrAmount);
|
||||
int size = Math.min(qrCode.getHeight(), qrCode.getWidth());
|
||||
int size = Math.max(ivQrCode.getWidth(), ivQrCode.getHeight());
|
||||
Bitmap qr = generate(bcData.getUriString(), size, size);
|
||||
if (qr != null) {
|
||||
setQR(qr);
|
||||
@@ -422,8 +509,8 @@ public class ReceiveFragment extends Fragment {
|
||||
Bitmap bitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
|
||||
bitmap = addLogo(bitmap);
|
||||
return bitmap;
|
||||
} catch (WriterException e) {
|
||||
e.printStackTrace();
|
||||
} catch (WriterException ex) {
|
||||
Timber.e(ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ public abstract class SecureActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// set FLAG_SECURE to prevent screenshots in Release Mode
|
||||
if (!BuildConfig.DEBUG && !BuildConfig.FLAVOR_type.equals("alpha")) {
|
||||
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
|
||||
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
}
|
||||
}
|
||||
|
@@ -22,11 +22,11 @@ import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.m2049r.xmrwallet.BuildConfig;
|
||||
import com.m2049r.xmrwallet.R;
|
||||
|
||||
import java.util.Locale;
|
||||
@@ -78,6 +78,11 @@ public class ProgressDialog extends AlertDialog {
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// set FLAG_SECURE to prevent screenshots in Release Mode
|
||||
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProgress(int value, int max) {
|
||||
|
@@ -6,7 +6,6 @@ import android.os.Looper;
|
||||
|
||||
import com.m2049r.xmrwallet.R;
|
||||
import com.m2049r.xmrwallet.dialog.ProgressDialog;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
|
@@ -587,6 +587,11 @@ public class Helper {
|
||||
}
|
||||
});
|
||||
|
||||
// set FLAG_SECURE to prevent screenshots in Release Mode
|
||||
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
|
||||
openDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
|
||||
}
|
||||
|
||||
Helper.showKeyboard(openDialog);
|
||||
openDialog.show();
|
||||
}
|
||||
|
@@ -100,6 +100,7 @@ public class RestoreHeight {
|
||||
blockheight.put("2018-12-01", 1716687L);
|
||||
blockheight.put("2019-01-01", 1738923L);
|
||||
blockheight.put("2019-02-01", 1761435L);
|
||||
blockheight.put("2019-03-01", 1781681L);
|
||||
}
|
||||
|
||||
public long getHeight(String date) {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="8dp">
|
||||
@@ -90,7 +89,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/generate_mnemonic_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textMultiLine"
|
||||
android:inputType="textMultiLine|textVisiblePassword"
|
||||
android:textAlignment="textStart" />
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
|
@@ -79,9 +79,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:padding="12dp"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_search_orange_24dp" />
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -104,18 +104,13 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
<ImageView
|
||||
android:id="@+id/ivGunther"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivGunther"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="48dp" />
|
||||
</ScrollView>
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_gravity="center"
|
||||
android:padding="48dp" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/list"
|
||||
|
11
app/src/main/res/menu/receive_menu.xml
Normal file
11
app/src/main/res/menu/receive_menu.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_share"
|
||||
android:title="Share"
|
||||
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
</menu>
|
6
app/src/main/res/xml/filepaths.xml
Normal file
6
app/src/main/res/xml/filepaths.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<cache-path
|
||||
name="shared_images"
|
||||
path="images/" />
|
||||
</paths>
|
@@ -7,7 +7,7 @@ source script/env.sh
|
||||
cd $EXTERNAL_LIBS_BUILD_ROOT
|
||||
|
||||
url="https://github.com/m2049r/monero"
|
||||
version="release-v0.13.0-monerujo"
|
||||
version="release-v0.14.0-monerujo"
|
||||
|
||||
if [ ! -d "monero" ]; then
|
||||
git clone ${url} -b ${version}
|
||||
|
Reference in New Issue
Block a user