From 1eb438576d862df8bf8c7221a6bebee7e8dd85f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 6 Jul 2015 16:21:48 +0200 Subject: Better YubiKey UX flow for error handling --- .../keychain/ui/NfcOperationActivity.java | 29 +++- .../keychain/ui/base/BaseNfcActivity.java | 23 ++- OpenKeychain/src/main/res/layout/nfc_activity.xml | 158 ------------------ .../src/main/res/layout/nfc_operation_activity.xml | 179 +++++++++++++++++++++ OpenKeychain/src/main/res/values/strings.xml | 30 ++-- 5 files changed, 240 insertions(+), 179 deletions(-) delete mode 100644 OpenKeychain/src/main/res/layout/nfc_activity.xml create mode 100644 OpenKeychain/src/main/res/layout/nfc_operation_activity.xml (limited to 'OpenKeychain') 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_activity.xml deleted file mode 100644 index 992f8c14d..000000000 --- a/OpenKeychain/src/main/res/layout/nfc_activity.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml b/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml new file mode 100644 index 000000000..8b043861f --- /dev/null +++ b/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +