diff --git a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/BiometricPrompt.java b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/BiometricPrompt.java index 0a801a4..9ccfa8c 100644 --- a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/BiometricPrompt.java +++ b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/BiometricPrompt.java @@ -18,7 +18,6 @@ import android.annotation.SuppressLint; import android.app.Activity; -import android.app.ActivityManager; import android.app.Fragment; import android.app.FragmentManager; import android.arch.lifecycle.Lifecycle; @@ -35,12 +34,9 @@ import android.support.annotation.Nullable; import android.support.v4.hardware.fingerprint.FingerprintManagerCompat; import android.util.Log; -import android.widget.Toast; import java.lang.annotation.Retention; import java.security.Signature; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.Executor; import javax.crypto.Cipher; @@ -184,7 +180,7 @@ Mac getMac() { /** * Callback structure provided to {@link BiometricPrompt}. Users of {@link * BiometricPrompt} must provide an implementation of this for listening to - * fingerprint events. + * fingerprint Events. */ public abstract static class AuthenticationCallback { /** @@ -401,6 +397,8 @@ public boolean isDeviceCredentialAllowed() { } } + public static LifecycleEvents Events; + // Passed in from the client. private Activity mActivity; private Fragment mFragment; @@ -454,7 +452,7 @@ public void run() { */ private final LifecycleObserver mLifecycleObserver = new LifecycleObserver() { @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) - void onPause() { + void onPause(Fragment fragment) { if (!isChangingConfigurations() && !usingBiometricFragment()) { // May be null if no authentication is occurring. if (mFingerprintDialogFragment != null && mFingerprintHelperFragment != null) { @@ -464,14 +462,22 @@ void onPause() { } } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) - void onResume() { + void onResume(Fragment fragment) { if (!usingBiometricFragment()) { - mFingerprintDialogFragment = - (FingerprintDialogFragment) getFragmentManager().findFragmentByTag( - DIALOG_FRAGMENT_TAG); - mFingerprintHelperFragment = - (FingerprintHelperFragment) getFragmentManager().findFragmentByTag( - FINGERPRINT_HELPER_FRAGMENT_TAG); + FingerprintDialogFragment dialogFragment = (FingerprintDialogFragment) getFragmentManager().findFragmentByTag( + DIALOG_FRAGMENT_TAG); + if (dialogFragment == null && fragment instanceof FingerprintDialogFragment) { + dialogFragment = (FingerprintDialogFragment) fragment; + } + FingerprintHelperFragment helperFragment = (FingerprintHelperFragment) getFragmentManager().findFragmentByTag( + FINGERPRINT_HELPER_FRAGMENT_TAG); + + if (dialogFragment == null || helperFragment == null) { + return; + } + + mFingerprintDialogFragment = dialogFragment; + mFingerprintHelperFragment = helperFragment; if (DEBUG) Log.v(TAG, "FingerprintDialogFragment: " + mFingerprintDialogFragment); if (DEBUG) Log.v(TAG, "FingerprintHelperFragment: " + mFingerprintHelperFragment); @@ -501,8 +507,8 @@ void onResume() { * {@link AuthenticationCallback} after configuration changes. * * @param activity A reference to the client's activity. - * @param executor An executor to handle callback events. - * @param callback An object to receive authentication events. + * @param executor An executor to handle callback Events. + * @param callback An object to receive authentication Events. */ @SuppressLint("LambdaLast") public BiometricPrompt(@NonNull Activity activity, @@ -520,6 +526,8 @@ public BiometricPrompt(@NonNull Activity activity, mActivity = activity; mAuthenticationCallback = callback; mExecutor = executor; + + Events = new LifecycleEvents(mLifecycleObserver); } /** @@ -534,8 +542,8 @@ public BiometricPrompt(@NonNull Activity activity, * such as {@link Fragment#onCreate(Bundle)}. * * @param fragment A reference to the client's fragment. - * @param executor An executor to handle callback events. - * @param callback An object to receive authentication events. + * @param executor An executor to handle callback Events. + * @param callback An object to receive authentication Events. */ @SuppressLint("LambdaLast") public BiometricPrompt(@NonNull Fragment fragment, @@ -552,6 +560,8 @@ public BiometricPrompt(@NonNull Fragment fragment, mFragment = fragment; mAuthenticationCallback = callback; mExecutor = executor; + + Events = new LifecycleEvents(mLifecycleObserver); } /** @@ -640,7 +650,7 @@ public void onAuthenticationFailed() { if (fingerprintDialogFragment != null) { mFingerprintDialogFragment = fingerprintDialogFragment; } else { - mFingerprintDialogFragment = FingerprintDialogFragment.newInstance(mLifecycleObserver); + mFingerprintDialogFragment = FingerprintDialogFragment.newInstance(); } mFingerprintDialogFragment.setNegativeButtonListener(mNegativeButtonListener); diff --git a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintDialogFragment.java b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintDialogFragment.java index f189b45..4c41787 100644 --- a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintDialogFragment.java +++ b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintDialogFragment.java @@ -21,8 +21,6 @@ import android.app.Dialog; import android.app.DialogFragment; import android.arch.lifecycle.Lifecycle; -import android.arch.lifecycle.LifecycleObserver; -import android.arch.lifecycle.OnLifecycleEvent; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; @@ -46,8 +44,6 @@ import android.widget.ImageView; import android.widget.TextView; -import java.lang.reflect.Method; - /** * This class implements a custom AlertDialog that prompts the user for fingerprint authentication. * This class is not meant to be preserved across process death; for security reasons, the @@ -58,31 +54,6 @@ @SuppressLint("SyntheticAccessor") public class FingerprintDialogFragment extends DialogFragment { - private static class Events { - LifecycleObserver observer; - Events(LifecycleObserver observer) { - this.observer = observer; - } - - void raise(Lifecycle.Event event) { - Method[] methods = observer.getClass().getDeclaredMethods(); - for(Method mt : methods) { - if (mt.isAnnotationPresent(OnLifecycleEvent.class)) { - OnLifecycleEvent annotation = mt.getAnnotation(OnLifecycleEvent.class); - if (annotation.value() == event) { - try { - mt.invoke(observer); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } - } - } - - private static Events events; - private static final String TAG = "FingerprintDialogFrag"; private static final String KEY_DIALOG_BUNDLE = "SavedBundle"; @@ -117,9 +88,8 @@ void raise(Lifecycle.Event event) { /** * Creates a dialog requesting for Fingerprint authentication. */ - static FingerprintDialogFragment newInstance(LifecycleObserver observer) { + static FingerprintDialogFragment newInstance() { FingerprintDialogFragment fragment = new FingerprintDialogFragment(); - events = new Events(observer); return fragment; } @@ -239,7 +209,6 @@ public void onSaveInstanceState(@NonNull Bundle outState) { public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = getActivity(); - events.raise(Lifecycle.Event.ON_CREATE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mErrorColor = getThemedColorFor(android.R.attr.colorError); @@ -254,7 +223,7 @@ public void onResume() { super.onResume(); mLastState = STATE_NONE; updateFingerprintIcon(STATE_FINGERPRINT); - events.raise(Lifecycle.Event.ON_RESUME); + BiometricPrompt.Events.raise(Lifecycle.Event.ON_RESUME, this); } @Override @@ -262,7 +231,7 @@ public void onPause() { super.onPause(); // Remove everything since the fragment is going away. mHandler.removeCallbacksAndMessages(null); - events.raise(Lifecycle.Event.ON_PAUSE); + BiometricPrompt.Events.raise(Lifecycle.Event.ON_PAUSE, this); } @Override diff --git a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintHelperFragment.java b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintHelperFragment.java index 1b148b6..bbfa6b7 100644 --- a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintHelperFragment.java +++ b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/FingerprintHelperFragment.java @@ -18,6 +18,8 @@ import android.annotation.SuppressLint; import android.app.Fragment; +import android.arch.lifecycle.Lifecycle; +import android.arch.lifecycle.LifecycleObserver; import android.content.Context; import android.os.Bundle; import android.os.Handler; @@ -259,6 +261,18 @@ public void onCreate(@Nullable Bundle savedInstanceState) { mContext = getActivity(); } + @Override + public void onResume() { + super.onResume(); + BiometricPrompt.Events.raise(Lifecycle.Event.ON_RESUME, this); + } + + @Override + public void onPause() { + super.onPause(); + BiometricPrompt.Events.raise(Lifecycle.Event.ON_PAUSE, this); + } + @Override @SuppressWarnings("deprecation") @Nullable diff --git a/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/LifecycleEvents.java b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/LifecycleEvents.java new file mode 100644 index 0000000..7c9c876 --- /dev/null +++ b/android-biometric-compat/src/main/java/com/exxbrain/android/biometric/LifecycleEvents.java @@ -0,0 +1,31 @@ +package com.exxbrain.android.biometric; + +import android.app.Fragment; +import android.arch.lifecycle.Lifecycle; +import android.arch.lifecycle.LifecycleObserver; +import android.arch.lifecycle.OnLifecycleEvent; + +import java.lang.reflect.Method; + +class LifecycleEvents { + LifecycleObserver observer; + LifecycleEvents(LifecycleObserver observer) { + this.observer = observer; + } + + void raise(Lifecycle.Event event, Fragment fragment) { + Method[] methods = observer.getClass().getDeclaredMethods(); + for(Method mt : methods) { + if (mt.isAnnotationPresent(OnLifecycleEvent.class)) { + OnLifecycleEvent annotation = mt.getAnnotation(OnLifecycleEvent.class); + if (annotation.value() == event) { + try { + mt.invoke(observer, fragment); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } + } +}