diff --git a/app/build.gradle b/app/build.gradle index f1f71bca..4445b5cd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.m2049r.xmrwallet" minSdkVersion 21 targetSdkVersion 25 - versionCode 111 - versionName "1.6.1 'Nano S'" + versionCode 112 + versionName "1.6.2 'Nano S'" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 89197384..805781ce 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,10 +8,11 @@ <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" /> + <uses-permission android:name="android.permission.NFC" /> <application android:name=".XmrWalletApplication" - android:allowBackup="true" + android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" @@ -41,32 +42,12 @@ <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/usb_device_filter" /> - </activity> - - <!--activity - android:name=".util.UsbEventReceiverActivity" - android:excludeFromRecents="true" - android:exported="false" - android:label="@string/app_name" - android:noHistory="true" - android:process=":UsbEventReceiverActivityProcess" - android:taskAffinity="com.m2049r.xmrwallet.taskAffinityUsbEventReceiver" - android:theme="@style/Theme.Transparent"> - <intent-filter> - <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> - </intent-filter> - <meta-data - android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" - android:resource="@xml/usb_device_filter" /> - </activity--> - + <service android:name=".service.WalletService" android:description="@string/service_description" android:exported="false" android:label="Monero Wallet Service" /> - </application> - </manifest> \ No newline at end of file diff --git a/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java b/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java index 8ef124d0..ae797859 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/BaseActivity.java @@ -1,14 +1,33 @@ package com.m2049r.xmrwallet; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.nfc.FormatException; +import android.nfc.NdefMessage; +import android.nfc.NdefRecord; +import android.nfc.NfcAdapter; +import android.nfc.Tag; +import android.nfc.tech.Ndef; +import android.os.AsyncTask; +import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; +import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.widget.Toast; +import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.dialog.ProgressDialog; +import com.m2049r.xmrwallet.fragment.send.SendFragment; import com.m2049r.xmrwallet.ledger.Ledger; import com.m2049r.xmrwallet.ledger.LedgerProgressDialog; +import java.io.IOException; + import timber.log.Timber; public class BaseActivity extends SecureActivity implements GenerateReviewFragment.ProgressListener { @@ -102,4 +121,174 @@ public class BaseActivity extends SecureActivity implements GenerateReviewFragme wl = null; Timber.d("WakeLock released"); } + + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initNfc(); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + if (nfcAdapter != null) { + nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, null, null); + // intercept all techs so we can tell the user their tag is no good + } + } + + @Override + protected void onPause() { + Timber.d("onPause()"); + if (nfcAdapter != null) + nfcAdapter.disableForegroundDispatch(this); + super.onPause(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + processNfcIntent(intent); + } + + // NFC stuff + private NfcAdapter nfcAdapter; + private PendingIntent nfcPendingIntent; + + public void initNfc() { + nfcAdapter = NfcAdapter.getDefaultAdapter(this); + if (nfcAdapter == null) // no NFC support + return; + nfcPendingIntent = PendingIntent.getActivity(this, 0, + new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), + 0); + } + + private void processNfcIntent(Intent intent) { + String action = intent.getAction(); + Timber.d("ACTION=%s", action); + if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) + || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) + || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { + Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); + Ndef ndef = Ndef.get(tag); + if (ndef == null) { + Toast.makeText(this, getString(R.string.nfc_tag_unsupported), Toast.LENGTH_LONG).show(); + return; + } + + Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container); + if (f instanceof ReceiveFragment) { + // We want to write a Tag from the ReceiveFragment + BarcodeData bc = ((ReceiveFragment) f).getBarcodeData(); + if (bc != null) { + new AsyncWriteTag(ndef, bc.getUri()).execute(); + } // else wallet is not loaded yet or receive is otherwise not ready - ignore + } else if (f instanceof SendFragment) { + // We want to read a Tag for the SendFragment + NdefMessage ndefMessage = ndef.getCachedNdefMessage(); + if (ndefMessage == null) { + Toast.makeText(this, getString(R.string.nfc_tag_read_undef), Toast.LENGTH_LONG).show(); + return; + } + NdefRecord firstRecord = ndefMessage.getRecords()[0]; + Uri uri = firstRecord.toUri(); // we insist on the first record + if (uri == null) { + Toast.makeText(this, getString(R.string.nfc_tag_read_undef), Toast.LENGTH_LONG).show(); + } else { + BarcodeData bc = BarcodeData.fromQrCode(uri.toString()); + if (bc == null) + Toast.makeText(this, getString(R.string.nfc_tag_read_undef), Toast.LENGTH_LONG).show(); + else + onUriScanned(bc); + } + } + } + } + + // this gets called only if we get data + @CallSuper + void onUriScanned(BarcodeData barcodeData) { + // do nothing by default yet + } + + private BarcodeData barcodeData = null; + + private BarcodeData popBarcodeData() { + BarcodeData popped = barcodeData; + barcodeData = null; + return popped; + } + + private class AsyncWriteTag extends AsyncTask<Void, Void, Boolean> { + + Ndef ndef; + Uri uri; + String errorMessage = null; + + AsyncWriteTag(Ndef ndef, Uri uri) { + this.ndef = ndef; + this.uri = uri; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + showProgressDialog(R.string.progress_nfc_write); + } + + @Override + protected Boolean doInBackground(Void... params) { + if (params.length != 0) return false; + try { + writeNdef(ndef, uri); + return true; + } catch (IOException | FormatException ex) { + Timber.e(ex); + } catch (IllegalArgumentException ex) { + errorMessage = ex.getMessage(); + Timber.d(errorMessage); + } finally { + try { + ndef.close(); + } catch (IOException ex) { + Timber.e(ex); + } + } + return false; + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + if (isDestroyed()) { + return; + } + dismissProgressDialog(); + if (!result) { + if (errorMessage != null) + Toast.makeText(getApplicationContext(), errorMessage, Toast.LENGTH_LONG).show(); + else + Toast.makeText(getApplicationContext(), getString(R.string.nfc_write_failed), Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(getApplicationContext(), getString(R.string.nfc_write_successful), Toast.LENGTH_SHORT).show(); + } + } + } + + void writeNdef(Ndef ndef, Uri uri) throws IOException, FormatException { + NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); + if (nfcAdapter == null) return; // no NFC support here + + NdefRecord recordNFC = NdefRecord.createUri(uri); + NdefMessage message = new NdefMessage(recordNFC); + ndef.connect(); + int tagSize = ndef.getMaxSize(); + int msgSize = message.getByteArrayLength(); + Timber.d("tagSize=%d, msgSIze=%d, uriSize=%d", tagSize, msgSize, uri.toString().length()); + if (tagSize < msgSize) + throw new IllegalArgumentException(getString(R.string.nfc_tag_size, tagSize, msgSize)); + ndef.writeNdefMessage(message); + } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java index 0c2ebb10..7b5e78b2 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java @@ -149,8 +149,7 @@ public class LoginActivity extends BaseActivity } else { Timber.i("Waiting for permissions"); } - - processIntent(getIntent()); + processUsbIntent(getIntent()); } boolean checkServiceRunning() { @@ -1255,10 +1254,10 @@ public class LoginActivity extends BaseActivity @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); - processIntent(intent); + processUsbIntent(intent); } - private void processIntent(Intent intent) { + private void processUsbIntent(Intent intent) { String action = intent.getAction(); if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { synchronized (this) { diff --git a/app/src/main/java/com/m2049r/xmrwallet/OnUriScannedListener.java b/app/src/main/java/com/m2049r/xmrwallet/OnUriScannedListener.java new file mode 100644 index 00000000..34fa1c5a --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/OnUriScannedListener.java @@ -0,0 +1,23 @@ +/* + * 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 com.m2049r.xmrwallet.data.BarcodeData; + +public interface OnUriScannedListener { + boolean onUriScanned(BarcodeData barcodeData); +} diff --git a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java index 8b19dd8d..99c9f210 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java @@ -20,6 +20,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; +import android.nfc.NfcAdapter; +import android.nfc.NfcManager; import android.os.AsyncTask; import android.os.Bundle; import android.support.design.widget.TextInputLayout; @@ -226,6 +228,12 @@ public class ReceiveFragment extends Fragment { throw new IllegalStateException("no wallet info"); } } + + View tvNfc = view.findViewById(R.id.tvNfc); + NfcManager manager = (NfcManager) getContext().getSystemService(Context.NFC_SERVICE); + if ((manager != null) && (manager.getDefaultAdapter() != null)) + tvNfc.setVisibility(View.VISIBLE); + return view; } @@ -257,7 +265,7 @@ public class ReceiveFragment extends Fragment { void setQR(Bitmap qr) { qrCode.setImageBitmap(qr); qrValid = true; - tvQrCode.setVisibility(View.INVISIBLE); + tvQrCode.setVisibility(View.GONE); Helper.hideKeyboard(getActivity()); etDummy.requestFocus(); } @@ -373,7 +381,6 @@ public class ReceiveFragment extends Fragment { } } - private boolean checkPaymentId() { String paymentId = etPaymentId.getEditText().getText().toString(); boolean ok = paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId); @@ -386,6 +393,15 @@ public class ReceiveFragment extends Fragment { return ok; } + public BarcodeData getBarcodeData() { + if (qrValid) + return bcData; + else + return null; + } + + private BarcodeData bcData = null; + private void generateQr() { Timber.d("GENQR"); String address = tvAddress.getText().toString(); @@ -397,27 +413,9 @@ public class ReceiveFragment extends Fragment { Timber.d("CLEARQR"); return; } - StringBuffer sb = new StringBuffer(); - sb.append(BarcodeData.XMR_SCHEME).append(address); - boolean first = true; - if (!paymentId.isEmpty()) { - if (first) { - sb.append("?"); - first = false; - } - sb.append(BarcodeData.XMR_PAYMENTID).append('=').append(paymentId); - } - if (!xmrAmount.isEmpty()) { - if (first) { - sb.append("?"); - } else { - sb.append("&"); - } - sb.append(BarcodeData.XMR_AMOUNT).append('=').append(xmrAmount); - } - String text = sb.toString(); + bcData = new BarcodeData(BarcodeData.Asset.XMR, address, paymentId, xmrAmount); int size = Math.min(qrCode.getHeight(), qrCode.getWidth()); - Bitmap qr = generate(text, size, size); + Bitmap qr = generate(bcData.getUriString(), size, size); if (qr != null) { setQR(qr); Timber.d("SETQR"); diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java index e6d4fb00..bc91dd15 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java @@ -27,7 +27,6 @@ import android.content.pm.PackageManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.IBinder; -import android.os.PowerManager; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; import android.support.v4.app.Fragment; @@ -841,26 +840,39 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste } - private BarcodeData scannedData = null; - @Override public boolean onScanned(String qrCode) { // #gurke BarcodeData bcData = BarcodeData.fromQrCode(qrCode); if (bcData != null) { - this.scannedData = bcData; popFragmentStack(null); + Timber.d("AAA"); + onUriScanned(bcData); return true; } else { return false; } } + OnUriScannedListener onUriScannedListener = null; + @Override - public BarcodeData popScannedData() { - BarcodeData data = scannedData; - scannedData = null; - return data; + public void setOnUriScannedListener(OnUriScannedListener onUriScannedListener) { + this.onUriScannedListener = onUriScannedListener; + } + + @Override + void onUriScanned(BarcodeData barcodeData) { + super.onUriScanned(barcodeData); + boolean processed = false; + if (onUriScannedListener != null) { + processed = onUriScannedListener.onUriScanned(barcodeData); + } + if (!processed || (onUriScannedListener == null)) { + Toast.makeText(this, getString(R.string.nfc_tag_read_what), Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(this, getString(R.string.nfc_tag_read_success), Toast.LENGTH_SHORT).show(); + } } @Override diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java b/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java index 1471c895..10298f4c 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java +++ b/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java @@ -18,9 +18,7 @@ package com.m2049r.xmrwallet.data; import android.net.Uri; -import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.model.Wallet; -import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.util.BitcoinAddressValidator; import java.util.HashMap; @@ -45,6 +43,11 @@ public class BarcodeData { public String paymentId = null; public String amount = null; + public BarcodeData(String uri) { + this.asset = asset; + this.address = address; + } + public BarcodeData(Asset asset, String address) { this.asset = asset; this.address = address; @@ -63,6 +66,31 @@ public class BarcodeData { this.amount = amount; } + public Uri getUri() { + return Uri.parse(getUriString()); + } + + public String getUriString() { + if (asset != Asset.XMR) throw new IllegalStateException("We can only do XMR stuff!"); + StringBuilder sb = new StringBuilder(); + sb.append(BarcodeData.XMR_SCHEME).append(address); + boolean first = true; + if ((paymentId != null) && !paymentId.isEmpty()) { + sb.append("?"); + first = false; + sb.append(BarcodeData.XMR_PAYMENTID).append('=').append(paymentId); + } + if (!amount.isEmpty()) { + if (first) { + sb.append("?"); + } else { + sb.append("&"); + } + sb.append(BarcodeData.XMR_AMOUNT).append('=').append(amount); + } + return sb.toString(); + } + static public BarcodeData fromQrCode(String qrCode) { // check for monero uri BarcodeData bcData = parseMoneroUri(qrCode); diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java index e1db43b0..8a19e5c9 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java @@ -17,6 +17,7 @@ package com.m2049r.xmrwallet.fragment.send; import android.content.Context; +import android.nfc.NfcManager; import android.os.Bundle; import android.support.design.widget.TextInputLayout; import android.support.v7.widget.CardView; @@ -64,6 +65,8 @@ public class SendAddressWizardFragment extends SendWizardFragment { public interface Listener { void setBarcodeData(BarcodeData data); + BarcodeData getBarcodeData(); + void setMode(SendFragment.Mode mode); TxData getTxData(); @@ -83,8 +86,6 @@ public class SendAddressWizardFragment extends SendWizardFragment { public interface OnScanListener { void onScan(); - - BarcodeData popScannedData(); } @Override @@ -206,6 +207,11 @@ public class SendAddressWizardFragment extends SendWizardFragment { etDummy.requestFocus(); Helper.hideKeyboard(getActivity()); + View tvNfc = view.findViewById(R.id.tvNfc); + NfcManager manager = (NfcManager) getContext().getSystemService(Context.NFC_SERVICE); + if ((manager != null) && (manager.getDefaultAdapter() != null)) + tvNfc.setVisibility(View.VISIBLE); + return view; } @@ -298,11 +304,20 @@ public class SendAddressWizardFragment extends SendWizardFragment { public void onResume() { super.onResume(); Timber.d("onResume"); - BarcodeData data = onScanListener.popScannedData(); - sendListener.setBarcodeData(data); - if (data != null) { + processScannedData(); + } + + public void processScannedData(BarcodeData barcodeData) { + sendListener.setBarcodeData(barcodeData); + if (isResumed()) + processScannedData(); + } + + public void processScannedData() { + BarcodeData barcodeData = sendListener.getBarcodeData(); + if (barcodeData != null) { Timber.d("GOT DATA"); - String scannedAddress = data.address; + String scannedAddress = barcodeData.address; if (scannedAddress != null) { etAddress.getEditText().setText(scannedAddress); checkAddress(); @@ -310,7 +325,7 @@ public class SendAddressWizardFragment extends SendWizardFragment { etAddress.getEditText().getText().clear(); etAddress.setError(null); } - String scannedPaymenId = data.paymentId; + String scannedPaymenId = barcodeData.paymentId; if (scannedPaymenId != null) { etPaymentId.getEditText().setText(scannedPaymenId); checkPaymentId(); @@ -318,7 +333,8 @@ public class SendAddressWizardFragment extends SendWizardFragment { etPaymentId.getEditText().getText().clear(); etPaymentId.setError(null); } - } + } else + Timber.d("barcodeData=null"); } @Override diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java index 05dcdc8f..e2964a13 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendFragment.java @@ -37,16 +37,15 @@ import android.widget.EditText; import android.widget.Toast; import com.m2049r.xmrwallet.OnBackPressedListener; +import com.m2049r.xmrwallet.OnUriScannedListener; import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.PendingTx; import com.m2049r.xmrwallet.data.TxData; import com.m2049r.xmrwallet.data.TxDataBtc; -import com.m2049r.xmrwallet.dialog.HelpFragment; import com.m2049r.xmrwallet.layout.SpendViewPager; import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.util.Helper; -import com.m2049r.xmrwallet.util.NodeList; import com.m2049r.xmrwallet.util.Notice; import com.m2049r.xmrwallet.util.UserNotes; import com.m2049r.xmrwallet.widget.DotBar; @@ -62,7 +61,7 @@ public class SendFragment extends Fragment SendSettingsWizardFragment.Listener, SendConfirmWizardFragment.Listener, SendSuccessWizardFragment.Listener, - OnBackPressedListener { + OnBackPressedListener, OnUriScannedListener { private Listener activityCallback; @@ -86,6 +85,8 @@ public class SendFragment extends Fragment void setTitle(String title); void setSubtitle(String subtitle); + + void setOnUriScannedListener(OnUriScannedListener onUriScannedListener); } private EditText etDummy; @@ -99,10 +100,6 @@ public class SendFragment extends Fragment private Button bDone; - private View llXmrToEnabled; - private View ibXmrToInfoClose; - - static private int MAX_FALLBACK = Integer.MAX_VALUE; @Override @@ -121,7 +118,7 @@ public class SendFragment extends Fragment arrowNext = getResources().getDrawable(R.drawable.ic_navigate_next_white_24dp); ViewGroup llNotice = (ViewGroup) view.findViewById(R.id.llNotice); - Notice.showAll(llNotice,".*_send"); + Notice.showAll(llNotice, ".*_send"); spendViewPager = (SpendViewPager) view.findViewById(R.id.pager); pagerAdapter = new SpendPagerAdapter(getChildFragmentManager()); @@ -226,13 +223,20 @@ public class SendFragment extends Fragment Timber.d("onAttach %s", context); super.onAttach(context); if (context instanceof Listener) { - this.activityCallback = (Listener) context; + activityCallback = (Listener) context; + activityCallback.setOnUriScannedListener(this); } else { throw new ClassCastException(context.toString() + " must implement Listener"); } } + @Override + public void onDetach() { + activityCallback.setOnUriScannedListener(null); + super.onDetach(); + } + private SpendViewPager spendViewPager; private SpendPagerAdapter pagerAdapter; @@ -247,6 +251,18 @@ public class SendFragment extends Fragment } } + @Override + public boolean onUriScanned(BarcodeData barcodeData) { + if (spendViewPager.getCurrentItem() == SpendPagerAdapter.POS_ADDRESS) { + final SendWizardFragment fragment = pagerAdapter.getFragment(SpendPagerAdapter.POS_ADDRESS); + if (fragment instanceof SendAddressWizardFragment) { + ((SendAddressWizardFragment) fragment).processScannedData(barcodeData); + return true; + } + } + return false; + } + enum Mode { XMR, BTC } @@ -414,8 +430,14 @@ public class SendFragment extends Fragment barcodeData = data; } + @Override + public BarcodeData getBarcodeData() { + return barcodeData; + } + @Override public BarcodeData popBarcodeData() { + Timber.d("POPPED"); BarcodeData data = barcodeData; barcodeData = null; return data; diff --git a/app/src/main/res/drawable/ic_nfc_black_24dp.xml b/app/src/main/res/drawable/ic_nfc_black_24dp.xml new file mode 100644 index 00000000..b73cdb03 --- /dev/null +++ b/app/src/main/res/drawable/ic_nfc_black_24dp.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M20,2L4,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,20L4,20L4,4h16v16zM18,6h-5c-1.1,0 -2,0.9 -2,2v2.28c-0.6,0.35 -1,0.98 -1,1.72 0,1.1 0.9,2 2,2s2,-0.9 2,-2c0,-0.74 -0.4,-1.38 -1,-1.72L13,8h3v8L8,16L8,8h2L10,6L6,6v12h12L18,6z" /> +</vector> diff --git a/app/src/main/res/layout/fragment_receive.xml b/app/src/main/res/layout/fragment_receive.xml index 835b152c..a69b4980 100644 --- a/app/src/main/res/layout/fragment_receive.xml +++ b/app/src/main/res/layout/fragment_receive.xml @@ -128,37 +128,39 @@ android:text="@string/send_generate_paymentid_hint" android:textColor="@color/moneroGray" android:visibility="visible" /> - </LinearLayout> - <FrameLayout + <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> - <TextView - android:id="@+id/tvQrCode" - style="@style/MoneroFab" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:drawablePadding="4dp" - android:drawableStart="@drawable/ic_info_outline_gray_24dp" - android:text="@string/label_receive_info_gen_qr_code" - android:textAlignment="center" - android:textSize="16sp" - android:visibility="invisible" /> - <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_gravity="center" + android:layout_above="@id/tvNfc" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" android:layout_margin="16dp" android:clickable="true" + android:focusable="true" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="2dp" card_view:cardElevation="8dp" card_view:contentPadding="4dp"> + <TextView + android:id="@+id/tvQrCode" + style="@style/MoneroFab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:drawablePadding="4dp" + android:drawableStart="@drawable/ic_info_outline_gray_24dp" + android:text="@string/label_receive_info_gen_qr_code" + android:textAlignment="center" + android:textSize="16sp" + android:visibility="gone" /> + <ImageView android:id="@+id/qrCode" android:layout_width="match_parent" @@ -166,7 +168,19 @@ android:adjustViewBounds="true" android:background="#00000000" /> </android.support.v7.widget.CardView> - </FrameLayout> + + <TextView + android:id="@+id/tvNfc" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_centerHorizontal="true" + android:gravity="center" + android:drawablePadding="8dp" + android:drawableStart="@drawable/ic_nfc_black_24dp" + android:text="@string/nfc_tag_tap" + android:visibility="visible" /> + </RelativeLayout> </LinearLayout> <ImageView diff --git a/app/src/main/res/layout/fragment_send_address.xml b/app/src/main/res/layout/fragment_send_address.xml index e52602a6..9f3a14e0 100644 --- a/app/src/main/res/layout/fragment_send_address.xml +++ b/app/src/main/res/layout/fragment_send_address.xml @@ -125,6 +125,7 @@ android:layout_gravity="center" android:layout_marginTop="32dp" android:clickable="true" + android:focusable="true" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="2dp" card_view:cardElevation="8dp" @@ -138,7 +139,17 @@ android:gravity="center" android:text="@string/send_qr_hint" android:textSize="20dp" /> - </android.support.v7.widget.CardView> + <TextView + android:id="@+id/tvNfc" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="8dp" + android:drawablePadding="8dp" + android:drawableStart="@drawable/ic_nfc_black_24dp" + android:gravity="center" + android:text="@string/nfc_tag_tap" + android:visibility="visible" /> </LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3986943f..2e9355af 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -338,4 +338,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 8fdd6195..81cd2f2f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -337,4 +337,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8195dde6..e071aaf4 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -324,4 +324,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 5635e4c5..1dbc4e53 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -340,4 +340,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 3a38acea..9a6ff7ee 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -338,4 +338,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index b7b03f85..dd00b8bf 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -339,4 +339,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 2ba58903..8c9edee8 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -337,4 +337,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index aeed5bc6..b4af8cd1 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -340,4 +340,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 2d190188..f9107313 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -337,4 +337,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a45a9137..625c98a0 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -339,4 +339,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index d0651b24..11ed9347 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -321,4 +321,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index a0d3beca..9c2eea37 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -335,4 +335,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b71d37fa..c91f1db7 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -336,4 +336,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 364ebb42..5541f47c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -384,4 +384,14 @@ <string name="toast_ledger_attached">%1$s attached</string> <string name="toast_ledger_detached">%1$s detached</string> + + <string name="progress_nfc_write">Writing Tag</string> + <string name="nfc_write_failed">Writing Tag failed!</string> + <string name="nfc_write_successful">Writing Tag successful</string> + <string name="nfc_tag_unsupported">Tag does not support NDEF!</string> + <string name="nfc_tag_size">Tag provides %d bytes, but we need %d!</string> + <string name="nfc_tag_read_undef">I don\'t understand the Tag!</string> + <string name="nfc_tag_read_what">I don\'t know what you want!</string> + <string name="nfc_tag_read_success">Reading Tag successful</string> + <string name="nfc_tag_tap">NFC Available!</string> </resources>