diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
index cacfd2e52..8802cd621 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
@@ -9,7 +9,9 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.view.View;
import android.view.WindowManager;
+import android.widget.Button;
import android.widget.TextView;
import android.widget.ViewAnimator;
@@ -49,6 +51,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
public ViewAnimator vAnimator;
public TextView vErrorText;
+ public Button vErrorTryAgainButton;
private RequiredInputParcel mRequiredInput;
private Intent mServiceIntent;
@@ -68,7 +71,20 @@ public class NfcOperationActivity extends BaseNfcActivity {
vAnimator = (ViewAnimator) findViewById(R.id.view_animator);
vAnimator.setDisplayedChild(0);
- vErrorText = (TextView) findViewById(R.id.nfc_activity_error_text);
+ vErrorText = (TextView) findViewById(R.id.nfc_activity_3_error_text);
+ vErrorTryAgainButton = (Button) findViewById(R.id.nfc_activity_3_error_try_again);
+ vErrorTryAgainButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ resumeTagHandling();
+
+ // obtain passphrase for this subkey
+ if (mRequiredInput.mType != RequiredInputParcel.RequiredInputType.NFC_MOVE_KEY_TO_CARD) {
+ obtainYubiKeyPin(mRequiredInput);
+ }
+ vAnimator.setDisplayedChild(0);
+ }
+ });
Intent intent = getIntent();
Bundle data = intent.getExtras();
@@ -84,7 +100,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
@Override
protected void initLayout() {
- setContentView(R.layout.nfc_activity);
+ setContentView(R.layout.nfc_operation_activity);
}
@Override
@@ -221,8 +237,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
if (isNfcConnected()) {
try {
Thread.sleep(200);
- } catch (InterruptedException e) {
- // never mind
+ } catch (InterruptedException ignored) {
}
} else {
return null;
@@ -239,7 +254,9 @@ public class NfcOperationActivity extends BaseNfcActivity {
@Override
protected void onNfcError(String error) {
- vErrorText.setText(error);
+ pauseTagHandling();
+
+ vErrorText.setText(error + "\n\n" + getString(R.string.nfc_try_again_text));
vAnimator.setDisplayedChild(3);
}
@@ -270,8 +287,6 @@ public class NfcOperationActivity extends BaseNfcActivity {
// clear (invalid) passphrase
PassphraseCacheService.clearCachedPassphrase(
this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
-
- obtainYubiKeyPin(mRequiredInput);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
index 02e8271cb..65f8a451c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
@@ -29,6 +29,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
+import android.nfc.TagLostException;
import android.nfc.tech.IsoDep;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -72,6 +73,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
protected boolean mPw3Validated;
private NfcAdapter mNfcAdapter;
private IsoDep mIsoDep;
+ private boolean mTagHandlingEnabled;
private static final int TIMEOUT = 100000;
@@ -168,10 +170,20 @@ public abstract class BaseNfcActivity extends BaseActivity {
}.execute();
}
+ protected void pauseTagHandling() {
+ mTagHandlingEnabled = false;
+ }
+
+ protected void resumeTagHandling() {
+ mTagHandlingEnabled = true;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mTagHandlingEnabled = true;
+
Intent intent = getIntent();
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
@@ -186,7 +198,8 @@ public abstract class BaseNfcActivity extends BaseActivity {
*/
@Override
public void onNewIntent(final Intent intent) {
- if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
+ if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())
+ && mTagHandlingEnabled) {
handleIntentInBackground(intent);
}
}
@@ -194,6 +207,11 @@ public abstract class BaseNfcActivity extends BaseActivity {
private void handleNfcError(Exception e) {
Log.e(Constants.TAG, "nfc error", e);
+ if (e instanceof TagLostException) {
+ onNfcError(getString(R.string.error_nfc_tag_lost));
+ return;
+ }
+
short status;
if (e instanceof CardException) {
status = ((CardException) e).getResponseCode();
@@ -202,7 +220,8 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
// When entering a PIN, a status of 63CX indicates X attempts remaining.
if ((status & (short)0xFFF0) == 0x63C0) {
- onNfcError(getString(R.string.error_pin, status & 0x000F));
+ int tries = status & 0x000F;
+ onNfcError(getResources().getQuantityString(R.plurals.error_pin, tries, tries));
return;
}
diff --git a/OpenKeychain/src/main/res/layout/nfc_activity.xml b/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml
similarity index 71%
rename from OpenKeychain/src/main/res/layout/nfc_activity.xml
rename to OpenKeychain/src/main/res/layout/nfc_operation_activity.xml
index 992f8c14d..8b043861f 100644
--- a/OpenKeychain/src/main/res/layout/nfc_activity.xml
+++ b/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml
@@ -14,10 +14,6 @@
android:measureAllChildren="false"
android:minHeight="?listPreferredItemHeightSmall"
android:outAnimation="@anim/fade_out"
- android:paddingBottom="16dp"
- android:paddingLeft="24dp"
- android:paddingRight="24dp"
- android:paddingTop="16dp"
custom:initialView="3">
@@ -49,9 +48,12 @@
android:layout_height="wrap_content">
@@ -65,13 +67,13 @@
+
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index bccdb4f00..c3a887fd1 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -263,7 +263,8 @@
"Enter PIN to access YubiKey for '%s'"
"Hold YubiKey against the NFC marker at the back of your device."
"Keep the YubiKey at the back!"
- "Please take away the YubiKey now."
+ "Take away the YubiKey now."
+ "Take away the YubiKey now and press TRY AGAIN."
"Delete original files?"
"The following files will be deleted:%s"
"%1$d out of %2$d files have been deleted.%3$s"
@@ -1388,17 +1389,22 @@
"Import"
Different key stored on YubiKey!
"NFC Error: %s"
- "NFC: Incorrect PIN; %d tries remaining."
- "NFC: Smart card in termination state"
- "NFC: Wrong length for sent / received data"
- "NFC: Conditions of use not satisfied"
- "NFC: Security status not satisfied"
- "NFC: PIN blocked after too many attempts"
- "NFC: Key or object not found"
- "NFC: Unknown Error"
- "NFC: Card reported invalid data"
- "NFC: Card expected last command in a chain"
- "NFC: Card reported invalid %s byte"
+
+ - "Incorrect PIN!\n%d try remaining."
+ - "Incorrect PIN!\n%d tries remaining."
+
+ "YubiKey in termination state"
+ "Wrong length for sent / received data"
+ "Conditions of use not satisfied"
+ "Security status not satisfied"
+ "PIN blocked after too many attempts"
+ "Key or object not found"
+ "Unknown Error"
+ "YubiKey reported invalid data"
+ "YubiKey expected last command in a chain"
+ "YubiKey reported invalid %s byte"
+ "YubiKey has been taken off too early. Keep the YubiKey at the back until the operation finishes."
+ "Try again"
Default PIN was rejected!
Error creating temporary file.
Delete original file