From 4e920afe94cb6f2c49ad443368ec291f7ee92ef7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Aug 2017 21:39:36 +0200 Subject: [PATCH 1/2] rewrite NfcHelper --- .../keychain/ui/ViewKeyAdvShareFragment.java | 16 +- .../keychain/ui/keyview/ViewKeyActivity.java | 10 +- .../keychain/util/NfcHelper.java | 217 +++++++++--------- 3 files changed, 117 insertions(+), 126 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java index 6c7602079..5027ed4d2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -27,7 +27,6 @@ import android.app.Activity; import android.app.ActivityOptions; import android.content.ClipData; import android.content.ClipboardManager; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -39,6 +38,7 @@ import android.os.Build; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.support.v4.app.ActivityCompat; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -94,9 +94,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements View root = super.onCreateView(inflater, superContainer, savedInstanceState); View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer()); - ContentResolver contentResolver = ViewKeyAdvShareFragment.this.getActivity().getContentResolver(); - KeyRepository keyRepository = KeyRepository.createDatabaseInteractor(getContext()); - mNfcHelper = new NfcHelper(getActivity(), keyRepository); + mNfcHelper = NfcHelper.getInstance(); mFingerprintView = (TextView) view.findViewById(R.id.view_key_fingerprint); mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code); @@ -176,7 +174,11 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements vKeyNfcButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mNfcHelper.invokeNfcBeam(); + FragmentActivity activity = getActivity(); + if (activity == null) { + return; + } + mNfcHelper.invokeNfcBeam(activity); } }); } else { @@ -359,7 +361,9 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); // Prepare the NfcHelper - mNfcHelper.initNfc(mDataUri); + FragmentActivity activity = getActivity(); + KeyRepository keyRepository = KeyRepository.createDatabaseInteractor(activity); + mNfcHelper.initNfcIfSupported(activity, keyRepository, mDataUri); } static final String[] UNIFIED_PROJECTION = new String[]{ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java index 88e92ead0..74ac0f41a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java @@ -166,9 +166,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements private String mQrCodeLoaded; - // NFC - private NfcHelper mNfcHelper; - private static final int LOADER_ID_UNIFIED = 0; private boolean mIsSecret = false; @@ -321,10 +318,12 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements } }); + final NfcHelper nfcHelper = NfcHelper.getInstance(); + nfcHelper.initNfcIfSupported(this, mKeyRepository, mDataUri); mActionNfc.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mNfcHelper.invokeNfcBeam(); + nfcHelper.invokeNfcBeam(ViewKeyActivity.this); } }); @@ -332,9 +331,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements // or start new ones. getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); - mNfcHelper = new NfcHelper(this, mKeyRepository); - mNfcHelper.initNfc(mDataUri); - if (savedInstanceState == null && getIntent().hasExtra(EXTRA_DISPLAY_RESULT)) { OperationResult result = getIntent().getParcelableExtra(EXTRA_DISPLAY_RESULT); result.createNotify(this).show(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java index f0136c37e..e01a78846 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2013-2014 Dominik Schürmann - * Copyright (C) 2015 Kent Nguyen + * Copyright (C) 2017 Vincent Breitmoser * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,12 +29,14 @@ import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; +import android.nfc.NfcAdapter.CreateNdefMessageCallback; import android.nfc.NfcEvent; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Message; import android.provider.Settings; +import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -46,167 +48,156 @@ import org.sufficientlysecure.keychain.ui.util.Notify; /** * This class contains NFC functionality that can be shared across Fragments or Activities. */ - public class NfcHelper { - - private Activity mActivity; - private KeyRepository mKeyRepository; - - /** - * NFC: This handler receives a message from onNdefPushComplete - */ - private static NfcHandler mNfcHandler; - - private NfcAdapter mNfcAdapter; - private NfcAdapter.CreateNdefMessageCallback mNdefCallback; - private NfcAdapter.OnNdefPushCompleteCallback mNdefCompleteCallback; - private byte[] mNfcKeyringBytes; private static final int NFC_SENT = 1; - /** - * Initializes the NfcHelper. - */ - public NfcHelper(final Activity activity, final KeyRepository keyRepository) { - mActivity = activity; - mKeyRepository = keyRepository; - mNfcHandler = new NfcHandler(mActivity); + public static NfcHelper getInstance() { + return new NfcHelper(); } - /** - * Return true if the NFC Adapter of this Helper has any features enabled. - * - * @return true if this NFC Adapter has any features enabled - */ - public boolean isEnabled() { - return mNfcAdapter.isEnabled(); - } + private NfcHelper() { } + - /** - * NFC: Initialize NFC sharing if OS and device supports it - */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - public void initNfc(final Uri dataUri) { + public void initNfcIfSupported(final Activity activity, final KeyRepository keyRepository, final Uri dataUri) { // check if NFC Beam is supported (>= Android 4.1) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + return; + } - // Implementation for the CreateNdefMessageCallback interface - mNdefCallback = new NfcAdapter.CreateNdefMessageCallback() { - @Override - public NdefMessage createNdefMessage(NfcEvent event) { + // Check for available NFC Adapter + final NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity); + if (nfcAdapter == null) { + return; + } + + final NfcHandler nfcHandler = new NfcHandler(activity); + + // Implementation for the OnNdefPushCompleteCallback interface + final NfcAdapter.OnNdefPushCompleteCallback ndefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() { + @Override + public void onNdefPushComplete(NfcEvent event) { + // A handler is needed to send messages to the activity when this + // callback occurs, because it happens from a binder thread + nfcHandler.obtainMessage(NFC_SENT).sendToTarget(); + } + }; + + /* Retrieve mNfcKeyringBytes here asynchronously (to not block the UI) and init nfc adapter afterwards. + * nfcKeyringBytes can not be retrieved in createNdefMessage, because this process has no permissions + * to query the Uri. + */ + AsyncTask initTask = new AsyncTask() { + protected byte[] doInBackground(Void... unused) { + try { + long masterKeyId = keyRepository.getCachedPublicKeyRing(dataUri).extractOrGetMasterKeyId(); + return keyRepository.loadPublicKeyRingData(masterKeyId); + } catch (NotFoundException | PgpKeyNotFoundException e) { + Log.e(Constants.TAG, "key not found!", e); + return null; + } catch (IllegalStateException e) { + // we specifically handle the database error if the blob is too large: "Couldn't read row 0, col 0 + // from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it." + if (!e.getMessage().startsWith("Couldn't read row")) { + throw e; + } + Log.e(Constants.TAG, "key blob too large to retrieve", e); + return null; + } + } + + protected void onPostExecute(final byte[] keyringBytes) { + if (keyringBytes == null) { + Log.e(Constants.TAG, "Could not obtain keyring bytes, NFC not available!"); + } + + if (activity.isFinishing()) { + return; + } + + // Implementation for the CreateNdefMessageCallback interface + CreateNdefMessageCallback ndefCallback = new NfcAdapter.CreateNdefMessageCallback() { + @Override + public NdefMessage createNdefMessage(NfcEvent event) { /* * When a device receives a push with an AAR in it, the application specified in the AAR is * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to * guarantee that this activity starts when receiving a beamed message. For now, this code * uses the tag dispatch system. */ - return new NdefMessage(NdefRecord.createMime(Constants.MIME_TYPE_KEYS, - mNfcKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME)); - } - }; + return new NdefMessage(NdefRecord.createMime(Constants.MIME_TYPE_KEYS, keyringBytes), + NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME)); + } + }; - // Implementation for the OnNdefPushCompleteCallback interface - mNdefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() { - @Override - public void onNdefPushComplete(NfcEvent event) { - // A handler is needed to send messages to the activity when this - // callback occurs, because it happens from a binder thread - mNfcHandler.obtainMessage(NFC_SENT).sendToTarget(); - } - }; + // Register callback to set NDEF message + nfcAdapter.setNdefPushMessageCallback(ndefCallback, activity); + // Register callback to listen for message-sent success + nfcAdapter.setOnNdefPushCompleteCallback(ndefCompleteCallback, activity); - // Check for available NFC Adapter - mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity); - if (mNfcAdapter != null) { - /* - * Retrieve mNfcKeyringBytes here asynchronously (to not block the UI) - * and init nfc adapter afterwards. - * mNfcKeyringBytes can not be retrieved in createNdefMessage, because this process - * has no permissions to query the Uri. - */ - AsyncTask initTask = - new AsyncTask() { - protected Void doInBackground(Void... unused) { - try { - long masterKeyId = mKeyRepository.getCachedPublicKeyRing(dataUri) - .extractOrGetMasterKeyId(); - mNfcKeyringBytes = mKeyRepository.loadPublicKeyRingData(masterKeyId); - } catch (NotFoundException | PgpKeyNotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - } - - // no AsyncTask return (Void) - return null; - } - - protected void onPostExecute(Void unused) { - if (mActivity.isFinishing()) { - return; - } - - // Register callback to set NDEF message - mNfcAdapter.setNdefPushMessageCallback(mNdefCallback, - mActivity); - // Register callback to listen for message-sent success - mNfcAdapter.setOnNdefPushCompleteCallback(mNdefCompleteCallback, - mActivity); - } - }; - - initTask.execute(); + Log.d(Constants.TAG, "NFC NDEF enabled!"); } - } + }; + + initTask.execute(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public void invokeNfcBeam() { - // Check if device supports NFC - if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) { - Notify.create(mActivity, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + public void invokeNfcBeam(@NonNull final Activity activity) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return; } - // Check for available NFC Adapter - mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity); - if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) { - Notify.create(mActivity, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() { - @Override - public void onAction() { - Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS); - mActivity.startActivity(intentSettings); + + boolean hasNfc = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC); + if (!hasNfc) { + Notify.create(activity, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + return; + } + NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity); + + boolean isNfcEnabled = nfcAdapter != null && nfcAdapter.isEnabled(); + if (!isNfcEnabled) { + Notify.create(activity, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, + new Notify.ActionListener() { + @Override + public void onAction() { + Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS); + activity.startActivity(intentSettings); } }, R.string.menu_nfc_preferences).show(); return; } - if (!mNfcAdapter.isNdefPushEnabled()) { - Notify.create(mActivity, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() { + if (!nfcAdapter.isNdefPushEnabled()) { + Notify.create(activity, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() { @Override public void onAction() { Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS); - mActivity.startActivity(intentSettings); + activity.startActivity(intentSettings); } }, R.string.menu_beam_preferences).show(); return; } - mNfcAdapter.invokeBeam(mActivity); + nfcAdapter.invokeBeam(activity); } private static class NfcHandler extends Handler { - private final WeakReference mActivityReference; + private final WeakReference activityReference; - public NfcHandler(Activity activity) { - mActivityReference = new WeakReference<>(activity); + NfcHandler(Activity activity) { + activityReference = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { - if (mActivityReference.get() != null) { + if (activityReference.get() != null) { switch (msg.what) { case NFC_SENT: - Notify.create(mActivityReference.get(), R.string.nfc_successful, Notify.Style.OK).show(); + Notify.create(activityReference.get(), R.string.nfc_successful, Notify.Style.OK).show(); break; } } From b94a8c9dee63df0c4c6c6f70f468f873b0296cd5 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Aug 2017 22:13:05 +0200 Subject: [PATCH 2/2] remove nfc key transfer feature, this was broken anyways --- .../keychain/ui/ViewKeyAdvShareFragment.java | 28 --- .../keychain/ui/keyview/ViewKeyActivity.java | 25 --- .../keychain/util/NfcHelper.java | 207 ------------------ .../src/main/res/layout/view_key_activity.xml | 11 - .../layout/view_key_adv_share_fragment.xml | 17 -- 5 files changed, 288 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java index 5027ed4d2..f42580f9f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -38,7 +38,6 @@ import android.os.Build; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.support.v4.app.ActivityCompat; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -68,7 +67,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.NfcHelper; public class ViewKeyAdvShareFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { @@ -79,8 +77,6 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements private CardView mQrCodeLayout; private TextView mFingerprintView; - NfcHelper mNfcHelper; - private static final int LOADER_ID_UNIFIED = 0; private Uri mDataUri; @@ -94,8 +90,6 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements View root = super.onCreateView(inflater, superContainer, savedInstanceState); View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer()); - mNfcHelper = NfcHelper.getInstance(); - mFingerprintView = (TextView) view.findViewById(R.id.view_key_fingerprint); mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code); @@ -137,7 +131,6 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements View vFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share); View vFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard); View vKeyShareButton = view.findViewById(R.id.view_key_action_key_share); - View vKeyNfcButton = view.findViewById(R.id.view_key_action_key_nfc); View vKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard); ImageButton vKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger); View vKeyUploadButton = view.findViewById(R.id.view_key_action_upload); @@ -169,22 +162,6 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements } }); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - vKeyNfcButton.setVisibility(View.VISIBLE); - vKeyNfcButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - FragmentActivity activity = getActivity(); - if (activity == null) { - return; - } - mNfcHelper.invokeNfcBeam(activity); - } - }); - } else { - vKeyNfcButton.setVisibility(View.GONE); - } - vKeySafeSlingerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -359,11 +336,6 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); - - // Prepare the NfcHelper - FragmentActivity activity = getActivity(); - KeyRepository keyRepository = KeyRepository.createDatabaseInteractor(activity); - mNfcHelper.initNfcIfSupported(activity, keyRepository, mDataUri); } static final String[] UNIFIED_PROJECTION = new String[]{ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java index 74ac0f41a..f7b08944a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java @@ -34,7 +34,6 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.net.Uri; -import android.nfc.NfcAdapter; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; @@ -112,7 +111,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.NfcHelper; import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Preferences; @@ -157,7 +155,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements private ImageButton mActionEncryptFile; private ImageButton mActionEncryptText; - private ImageButton mActionNfc; private FloatingActionButton mFab; private ImageView mPhoto; private FrameLayout mPhotoLayout; @@ -208,7 +205,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements mActionEncryptFile = (ImageButton) findViewById(R.id.view_key_action_encrypt_files); mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text); - mActionNfc = (ImageButton) findViewById(R.id.view_key_action_nfc); mFab = (FloatingActionButton) findViewById(R.id.fab); mPhoto = (ImageView) findViewById(R.id.view_key_photo); mPhotoLayout = (FrameLayout) findViewById(R.id.view_key_photo_layout); @@ -221,7 +217,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements ContentDescriptionHint.setup(mActionEncryptFile); ContentDescriptionHint.setup(mActionEncryptText); - ContentDescriptionHint.setup(mActionNfc); ContentDescriptionHint.setup(mFab); @@ -318,15 +313,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements } }); - final NfcHelper nfcHelper = NfcHelper.getInstance(); - nfcHelper.initNfcIfSupported(this, mKeyRepository, mDataUri); - mActionNfc.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - nfcHelper.invokeNfcBeam(ViewKeyActivity.this); - } - }); - // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); @@ -994,7 +980,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements mActionEncryptFile.setVisibility(View.INVISIBLE); mActionEncryptText.setVisibility(View.INVISIBLE); - mActionNfc.setVisibility(View.INVISIBLE); hideFab(); mQrCodeLayout.setVisibility(View.GONE); } else if (!mIsSecure) { @@ -1006,7 +991,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements mActionEncryptFile.setVisibility(View.INVISIBLE); mActionEncryptText.setVisibility(View.INVISIBLE); - mActionNfc.setVisibility(View.INVISIBLE); hideFab(); mQrCodeLayout.setVisibility(View.GONE); } else if (mIsExpired) { @@ -1018,7 +1002,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements mActionEncryptFile.setVisibility(View.INVISIBLE); mActionEncryptText.setVisibility(View.INVISIBLE); - mActionNfc.setVisibility(View.INVISIBLE); hideFab(); mQrCodeLayout.setVisibility(View.GONE); } else if (mIsSecret) { @@ -1055,13 +1038,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements mActionEncryptFile.setVisibility(View.VISIBLE); mActionEncryptText.setVisibility(View.VISIBLE); - // invokeBeam is available from API 21 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - && NfcAdapter.getDefaultAdapter(this) != null) { - mActionNfc.setVisibility(View.VISIBLE); - } else { - mActionNfc.setVisibility(View.INVISIBLE); - } showFab(); // noinspection deprecation (no getDrawable with theme at current minApi level 15!) mFab.setImageDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp)); @@ -1069,7 +1045,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements mActionEncryptFile.setVisibility(View.VISIBLE); mActionEncryptText.setVisibility(View.VISIBLE); mQrCodeLayout.setVisibility(View.GONE); - mActionNfc.setVisibility(View.INVISIBLE); if (mIsVerified) { mStatusText.setText(R.string.view_key_verified); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java deleted file mode 100644 index e01a78846..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * Copyright (C) 2017 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.util; - - -import java.lang.ref.WeakReference; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.nfc.NdefMessage; -import android.nfc.NdefRecord; -import android.nfc.NfcAdapter; -import android.nfc.NfcAdapter.CreateNdefMessageCallback; -import android.nfc.NfcEvent; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Handler; -import android.os.Message; -import android.provider.Settings; -import android.support.annotation.NonNull; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; -import org.sufficientlysecure.keychain.provider.KeyRepository; -import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException; -import org.sufficientlysecure.keychain.ui.util.Notify; - -/** - * This class contains NFC functionality that can be shared across Fragments or Activities. - */ -public class NfcHelper { - private static final int NFC_SENT = 1; - - - public static NfcHelper getInstance() { - return new NfcHelper(); - } - - private NfcHelper() { } - - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - public void initNfcIfSupported(final Activity activity, final KeyRepository keyRepository, final Uri dataUri) { - // check if NFC Beam is supported (>= Android 4.1) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - return; - } - - // Check for available NFC Adapter - final NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity); - if (nfcAdapter == null) { - return; - } - - final NfcHandler nfcHandler = new NfcHandler(activity); - - // Implementation for the OnNdefPushCompleteCallback interface - final NfcAdapter.OnNdefPushCompleteCallback ndefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() { - @Override - public void onNdefPushComplete(NfcEvent event) { - // A handler is needed to send messages to the activity when this - // callback occurs, because it happens from a binder thread - nfcHandler.obtainMessage(NFC_SENT).sendToTarget(); - } - }; - - /* Retrieve mNfcKeyringBytes here asynchronously (to not block the UI) and init nfc adapter afterwards. - * nfcKeyringBytes can not be retrieved in createNdefMessage, because this process has no permissions - * to query the Uri. - */ - AsyncTask initTask = new AsyncTask() { - protected byte[] doInBackground(Void... unused) { - try { - long masterKeyId = keyRepository.getCachedPublicKeyRing(dataUri).extractOrGetMasterKeyId(); - return keyRepository.loadPublicKeyRingData(masterKeyId); - } catch (NotFoundException | PgpKeyNotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - return null; - } catch (IllegalStateException e) { - // we specifically handle the database error if the blob is too large: "Couldn't read row 0, col 0 - // from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it." - if (!e.getMessage().startsWith("Couldn't read row")) { - throw e; - } - Log.e(Constants.TAG, "key blob too large to retrieve", e); - return null; - } - } - - protected void onPostExecute(final byte[] keyringBytes) { - if (keyringBytes == null) { - Log.e(Constants.TAG, "Could not obtain keyring bytes, NFC not available!"); - } - - if (activity.isFinishing()) { - return; - } - - // Implementation for the CreateNdefMessageCallback interface - CreateNdefMessageCallback ndefCallback = new NfcAdapter.CreateNdefMessageCallback() { - @Override - public NdefMessage createNdefMessage(NfcEvent event) { - /* - * When a device receives a push with an AAR in it, the application specified in the AAR is - * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to - * guarantee that this activity starts when receiving a beamed message. For now, this code - * uses the tag dispatch system. - */ - return new NdefMessage(NdefRecord.createMime(Constants.MIME_TYPE_KEYS, keyringBytes), - NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME)); - } - }; - - // Register callback to set NDEF message - nfcAdapter.setNdefPushMessageCallback(ndefCallback, activity); - // Register callback to listen for message-sent success - nfcAdapter.setOnNdefPushCompleteCallback(ndefCompleteCallback, activity); - - Log.d(Constants.TAG, "NFC NDEF enabled!"); - } - }; - - initTask.execute(); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public void invokeNfcBeam(@NonNull final Activity activity) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return; - } - - boolean hasNfc = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC); - if (!hasNfc) { - Notify.create(activity, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show(); - return; - } - NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity); - - boolean isNfcEnabled = nfcAdapter != null && nfcAdapter.isEnabled(); - if (!isNfcEnabled) { - Notify.create(activity, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, - new Notify.ActionListener() { - @Override - public void onAction() { - Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS); - activity.startActivity(intentSettings); - } - }, R.string.menu_nfc_preferences).show(); - - return; - } - - if (!nfcAdapter.isNdefPushEnabled()) { - Notify.create(activity, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() { - @Override - public void onAction() { - Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS); - activity.startActivity(intentSettings); - } - }, R.string.menu_beam_preferences).show(); - - return; - } - - nfcAdapter.invokeBeam(activity); - } - - private static class NfcHandler extends Handler { - private final WeakReference activityReference; - - NfcHandler(Activity activity) { - activityReference = new WeakReference<>(activity); - } - - @Override - public void handleMessage(Message msg) { - if (activityReference.get() != null) { - switch (msg.what) { - case NFC_SENT: - Notify.create(activityReference.get(), R.string.nfc_successful, Notify.Style.OK).show(); - break; - } - } - } - } - -} \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/view_key_activity.xml b/OpenKeychain/src/main/res/layout/view_key_activity.xml index 7c021bec2..7cfaaa30d 100644 --- a/OpenKeychain/src/main/res/layout/view_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/view_key_activity.xml @@ -111,17 +111,6 @@ android:src="@drawable/ic_action_encrypt_text_24dp" android:visibility="invisible" tools:visibility="visible" /> - - - - - - -