Marshmallow Fingerprint Scanner Hardware Presence

2019-02-14 05:39发布

问题:

I am looking to get started with the Marshmallow Fingerprint Authentication API. I understand that to ask for permission, I must use the following method:

ContextCompat.checkSelfPermission(getContext(), Manifest.permission.USE_FINGERPRINT);

And I must check if the device is running API level 23 or higher. But before I ask for permission, I would like to check if the device actually has a fingerprint scanner to begin with. I found the following two methods to do this check:

FingerprintManager manager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);

manager.isHardwareDetected();

manager.hasEnrolledFingerprints();

But both methods require USE_FINGERPRINT permission to be called at all. Why would I want to ask for permission to use a fingerprint scanner that I do not even know exists? Are there any other methods to find out if a scanner exists? Or is the only way to ask for permission first?

回答1:

I just found the class FingerprintManagerCompat, which does exactly what you would expect:

A class that coordinates access to the fingerprint hardware.

On platforms before M, this class behaves as there would be no fingerprint hardware available.

The same methods from FingerprintManager in this class do not require USE_FINGERPRINT permission, enabling you to call them before you ask for USE_FINGERPRINT permission.

FingerprintManagerCompat manager = FingerprintManagerCompat.from(mContext);

manager.isHardwareDetected();
manager.hasEnrolledFingerprints();

These methods will also yield the expected false results on pre-Marshmallow devices.



回答2:

Try hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) on a PackageManager instance (you can get one from calling getPackageManager() on any handy Context).



回答3:

FingerprintManager class supports Android devices running on API 23 or higher and throws an exception on devices running lower Android versions.

FingerprintManagerCompat class give backward compatibility of isHardwareDetected method in lower Android Version but it always returns false for API 23 or higher

I picked best of both and created this method to check for FingerPrint Sensor hardware support in all Android version.

  private boolean isSensorAvialable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return ActivityCompat.checkSelfPermission(AppContext, Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED &&
                    AppContext.getSystemService(FingerprintManager.class).isHardwareDetected();
        } else {
            return FingerprintManagerCompat.from(AppContext).isHardwareDetected();
        }
    }


回答4:

@CommonsWare mentioned something important, hasSystemFeature. To be on the safe side, if your using Java, make sure you call hasSystemFeature or check for null FingerprintManager return value when calling getSystermService even on devices running API 23 or higher. For Kotlin, use an optional variable and do a smart cast when calling getSystemService to avoid unpredictable crashes in the wild for devices without the Fingerprint hardware but running API 23 or greater.