In Biometric Prompt Dialog biometric icon is not showing in Android 11 - android

Android device Mi 10T and android version is 11
On click of button biometric prompt dialog is showing but biometric icon is not showing in that prompt dialog.
Below is Biometric Dialog's code
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle(activity.getString(R.string.login))
.setSubtitle(activity.getString(R.string.using_your_bimetric_credential))
.setNegativeButtonText("Cancel")
.setConfirmationRequired(false)
.build();
executor = ContextCompat.getMainExecutor(Objects.requireNonNull(activity));
biometricPrompt = new BiometricPrompt((FragmentActivity) activity,
executor, biometricPromptCallback);
biometricPrompt.authenticate(promptInfo);

/**
* Check the device supports for biometric authentication
*/
private void checkBiometricSupport() {
Boolean isBiometricSupported = false;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
BiometricManager biometricManager = BiometricManager.from(this);
switch (biometricManager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
case BiometricManager.BIOMETRIC_SUCCESS:
Log.d("MY_APP_TAG", "App can authenticate using biometrics.");
isBiometricSupported = true;
break;
case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
Log.e("MY_APP_TAG", "No biometric features available on this device.");
isBiometricSupported = false;
break;
case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
Log.e("MY_APP_TAG", "Biometric features are currently unavailable.");
isBiometricSupported = false;
break;
case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
isBiometricSupported = false;
// Prompts the user to create credentials that your app accepts.
final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
biometricEnrollResultLauncher.launch(enrollIntent);
break;
}
} else {
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (!keyguardManager.isKeyguardSecure()) {
showToast("Fingerprint authentication has not been enabled in settings. ");
isBiometricSupported = false;
}
if ((ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_BIOMETRIC) != PackageManager.PERMISSION_GRANTED)) {
showToast("Fingerprint authentication permission is not enabled. ");
isBiometricSupported = false;
}
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
showToast("Fingerprint is not supported ");
isBiometricSupported = false;
}
}
if (isBiometricSupported) {
dialogBioMetricPrompt();
}
}

Related

How to detect fingerprint hardware in android 11

How to detect that the phone has fingerprint hardware or not. I want a code that detects the fingerprint hardware.
I used this code but this code is showing an error on "isHardwareDetected()" this method.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Fingerprint API only available on from Android 6.0 (M)
FingerprintManager fingerprintManager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
if (!fingerprintManager.isHardwareDetected()) {
// Device doesn't support fingerprint authentication
} else if (!fingerprintManager.hasEnrolledFingerprints()) {
// User hasn't enrolled any fingerprints to authenticate with
} else {
// Everything is ready for fingerprint authentication
}
}
I made a minor change in the question code and now it is working fine.
But that class "FingerprintManagerCompat" is deprecated
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val manager = FingerprintManagerCompat.from(this)
if (!manager.isHardwareDetected) {
Log.e("tag","Fingerprint hardware not detected.")
} else if (!manager.hasEnrolledFingerprints()) {
Log.e("tag","No fingerprint is set")
} else {
Log.e("tag","Fingerprint is set")
}
}
Add the following code inside AndroidManifest.xml :
<uses-feature android:name="android.hardware.fingerprint" android:required="true" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
Use this where you require to detect the hardware:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
if (!fingerprintManager.isHardwareDetected()) {
Toast.makeText(getApplicationContext(), "Your device doesn't support fingerprint authentication", Toast.LENGTH_SHORT).show();
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Please enable the fingerprint permission", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.USE_FINGERPRINT}, FingerprintHandler.FINGERPRINT_PERMISSION);
}
if (!fingerprintManager.hasEnrolledFingerprints()) {
Toast.makeText(getApplicationContext(), "Your Device has no registered Fingerprints! Please register atleast one in your Device settings", Toast.LENGTH_LONG).show();
}
}

Android API 29 - check if connected to the cellular network

I am developing an SMS app and want to check for network (cellular) connection. With API level 29, checking for connection requires use of ConnectivityManager.NetworkCallback. What I have managed is to get 'onAvailable()` to inform me when a network becomes available. However, that will also inform me if it connects to WiFi (so I could have no service to send an SMS but if WiFI connects then onAvailable() will fire).
I tried onCapabilitiesChanged() and .hasTransport(TRANSPORT_CELLULAR) but that reports false if I am connected to WiFi.
I also thought to try hasCapability(NET_CAPABILITY_MMS) but that informs if MMS is possible. It's not clear to me if there is a scenario/network where SMS is possible but MMS is not? So could I get this reporting false because network does not support MMS but can still send SMS?
What is the correct method for checking if cellular network is available?
Maybe you can try the following
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean cellular = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
if(cellular){
// do your stuff
}
Late to the pary, and I'm not sure about 29... and I guess it is quite lame... but this is how I did it:
public boolean isCellularAvailable()
{
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
String opetarorName = telephonyManager.getNetworkOperatorName();
Log.i(LOG_TAG, "#### isCellularAvailable(): NetworkOperatorName is: " + opetarorName );
if (opetarorName .compareTo("") == 0)
{
Log.i(LOG_TAG, "#### isCellularAvailable(): NOPE");
Toast.makeText(context, "Turn off airplane mode and try again :)", Toast.LENGTH_LONG).show();
return false;
}
else
{
Log.i(LOG_TAG, "#### isCellularAvailable(): YES!");
return true;
}
}
The idea here is that if you are connected to a cellular network you should be able to get the name of your network provider.
If you get the name of one, then you are connected to that network, and should will be able to use it.
If you are in e.g. airplane mode, you will not be connected to a network, and will not get a name.
Noted that documentation says “Result may be unreliable on CDMA networks”… whatever that means.
But the “telephonyManager” offers a few similar functions, e.g. “getNetworkType()” might be another way to go if you know you´re favorable network types:
public boolean isCellularAvailable()
{
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
int networkType = telephonyManager.getNetworkType();// .getNetworkOperatorName();
Log.i(LOG_TAG, "#### isCellularAvailable(): Network type is: " + networkType);
switch (networkType)
{
// Return true for networks that suits your purpose
case TelephonyManager.NETWORK_TYPE_1xRTT: return true;
case TelephonyManager.NETWORK_TYPE_CDMA: return true;
case TelephonyManager.NETWORK_TYPE_EDGE: return true;
case TelephonyManager.NETWORK_TYPE_EHRPD: return true;
case TelephonyManager.NETWORK_TYPE_EVDO_0: return true;
case TelephonyManager.NETWORK_TYPE_EVDO_A: return true;
case TelephonyManager.NETWORK_TYPE_EVDO_B: return true;
case TelephonyManager.NETWORK_TYPE_GPRS: return true;
case TelephonyManager.NETWORK_TYPE_GSM: return true;
case TelephonyManager.NETWORK_TYPE_HSDPA: return true;
case TelephonyManager.NETWORK_TYPE_HSPA: return true;
case TelephonyManager.NETWORK_TYPE_HSPAP: return true;
case TelephonyManager.NETWORK_TYPE_HSUPA: return true;
case TelephonyManager.NETWORK_TYPE_IDEN: return true;
case TelephonyManager.NETWORK_TYPE_IWLAN: return true;
case TelephonyManager.NETWORK_TYPE_LTE: return true;
//case TelephonyManager.NETWORK_TYPE_NR: return true; // Not supported by my API
case TelephonyManager.NETWORK_TYPE_TD_SCDMA: return true;
case TelephonyManager.NETWORK_TYPE_UMTS: return true;
// Return false for unacceptable networks, UNKNOWN id no network e.g. airplane mode.
case TelephonyManager.NETWORK_TYPE_UNKNOWN: return false;
// Future unknown network types, handle as you please.
default: return false;
}
Try using following code to check if device is connected to internet or not.
ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
if (netInfo == null) {
Toast.makeText(this, "Please turn on Internet ", Toast.LENGTH_SHORT).show();
} else {
//do what you want
}
You need to use Network Callback.
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
connectivityManager.registerNetworkCallback(builder.build(),new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Variables.isNetworkConnected = true; // Global Static Variable
}
#Override
public void onLost(Network network) {
Variables.isNetworkConnected = false; // Global Static Variable
}
}
);
Variables.isNetworkConnected = false;
}catch (Exception e){
Variables.isNetworkConnected = false;
}
Variables.isNetworkConnected - Here I used a Global Static Variable, So I can use it to access the network state in anyware of the application.
Please refer this gist for full code implementation.

GET_ACCOUNT permission is not granted in android N

I am working on Account manager. I want to check account is exists or not.
private static final String TAG = "UserAccountUtil";
public static Account getAccount(Context context) {
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "GET_ACCOUNTS not present.");
}
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Constant.ACCOUNT_TYPE);
if (accounts.length > 0) {
Log.d(TAG, "GET_ACCOUNTS present..."+accounts[0]);
return accounts[0];
} else {
Log.d(TAG, "GET_ACCOUNTS not present...");
return null;
}
}
It always returns null or "GET_ACCOUNTS not present." in logs. I have added in manifest also.I am asking for run time permission also.
GET_ACCOUNTS--> Beginning with Android 6.0 (API level 23), if an app shares the
signature of the authenticator that manages an account, it does not
need "GET_ACCOUNTS" permission to read information about that account.
On Android 5.1 and lower, all apps need "GET_ACCOUNTS" permission to
read information about any account.The GET_ACCOUNTS permission is now Dead
You can use READ_CONTACTS permission instead of.
Check to Build.VERSION.SDK_INT
DEMO
if (accounts.length > 0 && android.os.Build.VERSION.SDK_INT<23 ) {
Log.d(TAG, "GET_ACCOUNTS present..."+accounts[0]);
return accounts[0];
} else {
Log.d(TAG, "GET_ACCOUNTS not present...");
return null;
}

How to enable Text to Speech/Talkback from another app in android

I've a requirement to enable or disable Text-to-Speech option from my app.
We will provide a button for the user. If TTS is enabled and user presses the button TTS will get disabled and if TTS is disabled and user presses the button TTS will get enabled.
Any idea on how can we enable/disable TTS on this button press?
Any help on this will be appreciated..
Note : This app will be signed as a system app.
I found the Answer for this question.
Answer: First we need to find out if we have Accessibility Services installed or not.
AccessibilityManager am = (AccessibilityManager)(Extension.mainContext.getSystemService(Context.ACCESSIBILITY_SERVICE));
List<AccessibilityServiceInfo> services = am.getInstalledAccessibilityServiceList();
Above given two lines will give us the install services for Accessibility/Talk Back.
After we have the services we can enable the permissions which we want for those services. Please see the enableTalkBack() below to see how to do that.
Note: To write into Secure Settings your android app needs to be signed as a system app because only system apps have permissions to write into secure settings.
public static void enableTalkBack()
{
try {
AccessibilityManager am = (AccessibilityManager)(Extension.mainContext.getSystemService(Context.ACCESSIBILITY_SERVICE));
List<AccessibilityServiceInfo> services = am.getInstalledAccessibilityServiceList();
if (services.isEmpty()) {
return;
}
AccessibilityServiceInfo service = services.get(0);
boolean enableTouchExploration = (service.flags
& AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
// Try to find a service supporting explore by touch.
if (!enableTouchExploration) {
final int serviceCount = services.size();
for (int i = 1; i < serviceCount; i++) {
AccessibilityServiceInfo candidate = services.get(i);
if ((candidate.flags & AccessibilityServiceInfo
.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0) {
enableTouchExploration = true;
service = candidate;
break;
}
}
}
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
ComponentName componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
String enabledServiceString = componentName.flattenToString();
ContentResolver resolver = Extension.mainContext.getContentResolver();
Settings.Secure.putString(resolver, "enabled_accessibility_services", enabledServiceString);
Settings.Secure.putString(resolver,
"touch_exploration_granted_accessibility_services",
enabledServiceString);
if (enableTouchExploration) {
Settings.Secure.putInt(resolver, "touch_exploration_enabled", 1);
}
Settings.Secure.putInt(resolver, "accessibility_script_injection", 1);
Settings.Secure.putInt(resolver, "accessibility_enabled", 1);
}
catch(Exception e) {
Log.e("Device", "Failed to enable accessibility: " + e);
}
}

SecurityException while checking if fingerprints are enrolled in Samsung Phones

I am using a lockscreen with fingerprint in my app. While it works seamlessly with other phones having fingerprint sensor, samsung users are facing some SecurityException as I can see in my google console reports.Here is the report:
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3319)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3415)
at android.app.ActivityThread.access$1100 (ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1821)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:148)
at android.app.ActivityThread.main (ActivityThread.java:7406)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)
Caused by: java.lang.SecurityException:
at android.os.Parcel.readException (Parcel.java:1621)
at android.os.Parcel.readException (Parcel.java:1574)
at android.hardware.fingerprint.IFingerprintService$Stub$Proxy.hasEnrolledFingerprints (IFingerprintService.java:503)
at android.hardware.fingerprint.FingerprintManager.hasEnrolledFingerprints (FingerprintManager.java:776)
at com.example.ark.access.LockScreen.setUpFingerPrint (LockScreen.java:252)
at com.example.ark.access.LockScreen.onCreate (LockScreen.java:67)
at android.app.Activity.performCreate (Activity.java:6904)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1136)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3266)
Here is the portion of my file which checks for fingerprints:
private void setUpFingerPrint(ImageView white,ImageView black)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Get an instance of KeyguardManager and FingerprintManager//
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
//Check whether the device has a fingerprint sensor//
if (!fingerprintManager.isHardwareDetected()) {
// If a fingerprint sensor isn’t available, then inform the user that they’ll be unable to use your app’s fingerprint functionality//
//Toast.makeText(this, R.string.noFingerPrint, Toast.LENGTH_SHORT).show();
white.setVisibility(View.GONE);
black.setVisibility(View.GONE);
}
//Check whether the user has granted your app the USE_FINGERPRINT permission//
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
// If your app doesn't have this permission, then display the following text//
Toast.makeText(this, R.string.noFingerPrintPermission, Toast.LENGTH_SHORT).show();
}
//Check that the user has registered at least one fingerprint//
if (!fingerprintManager.hasEnrolledFingerprints()) {
// If the user hasn’t configured any fingerprints, then display the following message//
Toast.makeText(this, R.string.noFingerPrintRegistered, Toast.LENGTH_SHORT).show();
}
//Check that the lockscreen is secured//
if (!keyguardManager.isKeyguardSecure()) {
// If the user hasn’t secured their lockscreen with a PIN password or pattern, then display the following text//
Toast.makeText(this, R.string.lockScreenNotConfigured, Toast.LENGTH_SHORT).show();
}
else {
try {
generateKey();
} catch (FingerprintException e) {
e.printStackTrace();
}
if (initCipher()) {
//If the cipher is initialized successfully, then create a CryptoObject instance//
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
// Here, I’m referencing the FingerprintHandler class that we’ll create in the next section. This class will be responsible
// for starting the authentication process (via the startAuth method) and processing the authentication process events//
int k = getIntent().getIntExtra("Mode", 0);
FingerprintHandler helper = new FingerprintHandler(this,k,white,black);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
}
else
{
white.setVisibility(View.GONE);
black.setVisibility(View.GONE);
}
}
Line 252 is the one having the check fingerprintmanager.hasEnrolledFingerprints()
I am having a hard time figuring it out as I have no samsung phones to test. Till now it has happened in Galaxy J7 and Grand Prime Plus.
Not sure if you were ever able to find a solution for this, as a workaround I simply wrapped our calls in a permission check.
inline val Activity.fingerprintManager: FingerprintManagerCompat?
get() = (
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED) {
FingerprintManagerCompat.from(this)
} else { null }
)
The solution that worked for me is this :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Get an instance of KeyguardManager and FingerprintManager//
KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(KEYGUARD_SERVICE);
FingerprintManager fingerprintManager = (FingerprintManager)context.getSystemService(FINGERPRINT_SERVICE);
//Check whether the device has a fingerprint sensor//
if (!fingerprintManager.isHardwareDetected()) {
// If a fingerprint sensor isn’t available, then inform the user that they’ll be unable to use your app’s fingerprint functionality//
//Toast.makeText(this, R.string.noFingerPrint, Toast.LENGTH_SHORT).show();
listener.noFingerPrintHardware();
} else {
//Check whether the user has granted your app the USE_FINGERPRINT permission//
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
listener.fingerPrintPermissionError();
} else {
//Check that the user has registered at least one fingerprint//
if (!fingerprintManager.hasEnrolledFingerprints()) {
listener.noEnrolledFingerprints();
} else {
//Check that the lockscreen is secured//
if (!keyguardManager.isKeyguardSecure()) {
listener.keygaurdNotSecure();
} else {
try {
generateKey();
} catch (FingerprintException e) {
e.printStackTrace();
}
if (initCipher(listener)) {
//If the cipher is initialized successfully, then create a CryptoObject instance//
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
// Here, I’m referencing the FingerprintHandler class that we’ll create in the next section. This class will be responsible
// for starting the authentication process (via the startAuth method) and processing the authentication process events//
FingerprintHandler helper = new FingerprintHandler(context,listener);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
}
}
}
}
else
{
listener.noFingerPrintHardware();
}
I put the checks in a nested-if format, where the fingerprint authentication starts only when all the checks are satisfied. There have been no such crashes since.
Do you request permission to access the fingerprint API in your application manifest?
You have to insert the following line into your app's permissions section.
<uses-permission android:name="android.permission.USE_FINGERPRINT" />

Categories

Resources