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?
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.
Try hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
on a PackageManager
instance (you can get one from calling getPackageManager()
on any handy Context
).
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();
}
}
@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.