com.aitorvs.android.fingerlock.FingerLockApi23.java Source code

Java tutorial

Introduction

Here is the source code for com.aitorvs.android.fingerlock.FingerLockApi23.java

Source

/*
 * Copyright (c) 2016 Aitor Viana Sanchez
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package com.aitorvs.android.fingerlock;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.Log;

import java.security.InvalidParameterException;

@TargetApi(Build.VERSION_CODES.M)
class FingerLockApi23 implements FingerLockApi.FingerLockImpl {

    private static final String TAG = FingerLockApi23.class.getSimpleName();
    private FingerprintAuthHandler mAuthenticationHandler;
    private Context mContext;
    private Key mKey;
    private FingerLockResultCallback mCallback;

    // specific of the implementation for API >=23
    private FingerprintManager mFingerprintManager;

    @Override
    public boolean isFingerprintAuthSupported() {
        invalidContext();

        // check permissions
        int granted = ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.USE_FINGERPRINT);
        if (granted != PackageManager.PERMISSION_GRANTED) {
            // not granted
            return false;
        }

        // return hardware support
        //noinspection MissingPermission
        return mFingerprintManager != null && mFingerprintManager.isHardwareDetected()
                && mFingerprintManager.hasEnrolledFingerprints();

    }

    @Override
    public boolean isFingerprintRegistered() {
        if (!isFingerprintAuthSupported()) {
            return false;
        }

        // no need to check for permissions, as it's done inside previous call
        //noinspection MissingPermission
        return mFingerprintManager != null && mFingerprintManager.hasEnrolledFingerprints();
    }

    @Override
    public void start() {
        if (!isFingerprintAuthSupported()) {
            mCallback.onFingerLockError(FingerLock.FINGERPRINT_NOT_SUPPORTED,
                    new Exception("Fingerprint authentication not supported in this device"));
        } else if (mAuthenticationHandler != null && mAuthenticationHandler.isStarted()) {
            // auth handler already listening...do nothing
        } else {
            try {
                mAuthenticationHandler = new FingerprintAuthHandler(null, mCallback);
                //noinspection MissingPermission
                mAuthenticationHandler.start(mFingerprintManager);

                mCallback.onFingerLockScanning(!mKey.isKeyValid());
            } catch (NullKeyException e) {
                // key is not yet created. Create it and retry
                mKey.recreateKey();
                try {
                    mCallback.onFingerLockScanning(!mKey.isKeyValid());
                } catch (NullKeyException e1) {
                    // something went wrong unregister and notify
                    stop();
                    mCallback.onFingerLockError(FingerLock.FINGERPRINT_UNRECOVERABLE_ERROR,
                            new Exception("Key creation failed."));
                }
            }
        }
    }

    @Override
    public void stop() {
        if (mAuthenticationHandler != null) {
            // cancel and flag it as self cancelled
            mAuthenticationHandler.stop(true);
        }
    }

    @Override
    public void register(@NonNull Context context, @NonNull final String keyName,
            @NonNull FingerLockResultCallback callback) {
        // double check
        //noinspection ConstantConditions
        if (context == null || callback == null || keyName == null) {
            throw new InvalidParameterException("Invalid or null input parameters");
        } else if (mCallback != null) {
            // already registered, force clean unregister
            forceUnregister();
        }
        if (BuildConfig.DEBUG)
            Log.d(TAG, "Registering " + keyName);

        mContext = context;
        mCallback = callback;
        mKey = new Key(keyName);

        mFingerprintManager = getFingerprintManager();

        if (!isFingerprintAuthSupported()) {
            callback.onFingerLockError(FingerLock.FINGERPRINT_NOT_SUPPORTED,
                    new Exception("Fingerprint authentication not supported in this device"));
        } else if (!isFingerprintRegistered()) {
            callback.onFingerLockError(FingerLock.FINGERPRINT_REGISTRATION_NEEDED,
                    new Exception("No fingerprints registered in this device"));
        } else {
            // all systems Go!
            callback.onFingerLockReady();
        }
    }

    @Override
    public void recreateKey(final FingerLockResultCallback listener) {
        if (mCallback == listener) {
            mKey.recreateKey();
        } else {
            if (BuildConfig.DEBUG)
                Log.d(TAG, "recreateKey: non-registered listener trying to recreate key");
        }
    }

    @Override
    public boolean inUseBy(FingerLockResultCallback listener) {
        if (BuildConfig.DEBUG)
            Log.d(TAG, "inUseBy: " + (mCallback == listener ? "true" : "false"));
        return mContext != null && mCallback != null && mCallback == listener;
    }

    @Override
    public boolean unregister(@NonNull FingerLockResultCallback listener) {
        if (mCallback == listener) {
            mCallback = null;
            mContext = null;

            stop();
            if (BuildConfig.DEBUG)
                Log.d(TAG, "unregister: OK");
            return true;
        }

        return false;
    }

    private void forceUnregister() {
        mCallback = null;
        mContext = null;

        stop();
        if (BuildConfig.DEBUG)
            Log.d(TAG, "Force unregister: OK");
    }

    private void invalidContext() throws IllegalStateException {
        if (mContext == null) {
            throw new IllegalStateException("Callback listener not registered");
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Nullable
    private FingerprintManager getFingerprintManager() {

        if (mFingerprintManager == null) {
            invalidContext();

            mFingerprintManager = (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE);
        }

        return mFingerprintManager;
    }
}