Android - Not granted USE_BIOMETRIC - android

I am checking all permisions from the Manifest with the code bellow. Now I added USE_BIOMETRIC permission, because I want to use fingerprint, but this permission is not granted and I don't know why.
I know that USE_BIOMETRIC is normal permission so it shouldn't be asked and should be granted when it's in the Manifest, but it's not.
Checking for other permissions is working and all are granted or asked for it, only this one is not.
I am testing app on 2 phones, emulated Google pixel with Android 8.0 and API 26 and physical Xiaomi Redmi 5 with Android 8.1 and API 27.
Both phones are using fingerprint to unlock screen.
Permisions in the manifest:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
Code that loads permissions from the manifest and check if is granted or not:
fun checkAndRequestPermissions(): Boolean{
var listPermissionsNeeded = ArrayList<String>()
val permissions = retrievePermissions(activity.baseContext)
permissions.forEach {
if(ContextCompat.checkSelfPermission(activity.baseContext, it) != PackageManager.PERMISSION_GRANTED){
listPermissionsNeeded.add(it)
Log.d("Missing permission", it)
}
}
if (!listPermissionsNeeded.isEmpty()) {
val array = arrayOfNulls<String>(listPermissionsNeeded.size)
listPermissionsNeeded.toArray(array)
ActivityCompat.requestPermissions(activity, array, ConstantsStorage.ACTIVITY_REQUEST_PERMISSIONS_CODE)
return false
}
return true
}
companion object {
/**
* Retrieves permissions listed in the manifest file
* #param context Context
* #return Returns String array of permissions
*/
fun retrievePermissions(context: Context): Array<String> {
try {
return context
.packageManager
.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS)
.requestedPermissions
} catch (e: PackageManager.NameNotFoundException) {
throw RuntimeException("This should have never happened.", e)
}
}
}
Thank you for your help

According to the new policy in Google Console, you couldn't use this permission on the Manifest. So you should Request and Check in Activity.
You can use BiometricManager to check it:
val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) {
BiometricManager.BIOMETRIC_SUCCESS ->
Log.d("MY_APP_TAG", "App can authenticate using biometrics.")
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
Log.e("MY_APP_TAG", "No biometric features available on this device.")
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
Log.e("MY_APP_TAG", "Biometric features are currently unavailable.")
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
// Prompts the user to create credentials that your app accepts.
val enrollIntent = Intent(Settings.ACTION_BIOMETRIC_ENROLL).apply {
putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
}
startActivityForResult(enrollIntent, REQUEST_CODE)
}
}
Note: It's very important to add suitable import
import androidx.biometric.BiometricManager;

Related

Need android.permission.BLUETOOTH_CONNECT permission for AttributionSource in Android 12

Migrating from android 30 to the android 31 version, I am trying to connect to the paired Bluetooth device in my app.
But, I am facing an issue when I tried to get the paired device list.
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices
pairedDevices?.forEach { device ->
if(device.address.lowercase() == configHelper.bluetoothAddress.lowercase()){
bluetoothDevice = device
paymentTerminalName = device.name
paymentTerminalMAC = device.address // MAC address
UUIDFromPaymentTerminal = device.uuids[0].uuid // UUID specifies the service that the the server provides
}
}
if(bluetoothDevice == null){
//payment terminal is not paired yet
throw ex
}
socket = bluetoothDevice!!.createRfcommSocketToServiceRecord(UUIDFromPaymentTerminal)
//cancel discovery, otherwise it slows down the connection process
bluetoothAdapter!!.cancelDiscovery()
(socket!! as BluetoothSocket).connect()
I am getting the below error,
java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT
permission for AttributionSource { uid = 10414, packageName =
com.test.app, attributionTag = null, token =
android.os.BinderProxy#8a4f87d, next = null }: AdapterService
getBondedDevices
I have added bluetooth permission to my manifest file,
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
Let me know where am I missing to get the paired device in kotlin 1.5.0
The BLUETOOTH_CONNECT & BLUETOOTH_SCAN permissions are runtime permissions, these permissions have to be asked during the runtime of your application.
The BLUETOOTH_SCAN permission should be asked before you scan for devices and the BLUETOOTH_CONNECT permission should be asked before you connect to a device.
An example of a permission requester for an single permission within the Fragments architecture:
val requestConnectPermission: ActivityResultLauncher<String> =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { permissionGranted ->
if (permissionGranted) {
// connect to device
}
}
An example of a requester for multiple permissions within the Fragments architecture:
val permissionRequester: ActivityResultLauncher<Array<String>> = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions.values.all { it }) {
// connect to device
}
}
To handle a single permission request within an Composable is slightly different, you can do the following:
val permissionRequester =
rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
// connect to device
}
}
requestConnectPermission?.launch(Manifest.permission.BLUETOOTH_CONNECT)
And for multiple permissions at once:
val permissionRequester =
rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions.values.all { it }) {
// connect to device
}
}
Before you should use such a permission launcher you should check if the user has already accepted the permissions. If not you can launch a request. An example to launch a single permission request:
if (ActivityCompat.checkSelfPermission(requireContext(), BLUETOOTH_CONNECT) == PERMISSION_GRANTED) {
// connect to device
} else {
permissionRequester.launch(BLUETOOTH_CONNECT)
}
And if you want to launch multiple permission requests at once you can do this:
if (ActivityCompat.checkSelfPermission(requireContext(), BLUETOOTH_CONNECT) == PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(requireContext(), BLUETOOTH_SCAN) == PERMISSION_GRANTED) {
// connect to device
} else {
permissionRequester.launch(arrayOf(BLUETOOTH_CONNECT, BLUETOOTH_SCAN))
}
More info about permissions can be found here.

Advertising id is 00000000-0000-0000-0000-000000000000 even after adding AD_ID permission to the manifest

I have targeted my android app to API 33. Also, as mentioned in the behavioural changes in Android13 doc I have added the following permission to the App's Manifest file.
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>
When I run the app and fetch the Google advertising id, I am still getting 00000000-0000-0000-0000-000000000000, whereas the documentation says you will only get zeroes if you have not added the permission in the manifest.
Also, I have not disabled app personalisation.
Following is my code to fetch the advertising id:
fun getAdvertisingIdInfo(context: Context): AdInfo {
check(Looper.myLooper() != Looper.getMainLooper()) { "Cannot be called from the main thread" }
try {
val pm = context.packageManager
pm.getPackageInfo("com.android.vending", 0)
} catch (e: Exception) {
throw e
}
val connection = AdvertisingConnection()
val intent = Intent("com.google.android.gms.ads.identifier.service.START")
intent.setPackage("com.google.android.gms")
if (context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
return try {
val adInterface = AdvertisingInterface(connection.binder)
AdInfo(adInterface.id, adInterface.isLimitAdTrackingEnabled(true))
} catch (exception: Exception) {
throw exception
} finally {
context.unbindService(connection)
}
}
throw IOException("Google Play connection failed")
}
Kindly note, I have only made one change, i.e. I have added the permission
The problem was with following attribute in uses-permission tag
tools:node="remove"
Basically this removes the permission when merging Manifests. You can remove this and you should be able to fetch the advertising id

I am making a gallery like UI for my app, what permissions do i need to ask for if I am targetting Android 11?

I am using MediaStore to recieve the ids of all the images stored on the device using
private fun getImageUris(): List<Uri> {
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID)
val mCursor = requireActivity().contentResolver.query(
uri,
projection,
null,
null,
null
)
val imageUris = mutableListOf<Uri>()
while (mCursor?.moveToNext() == true) {
val columnIndex = mCursor.getColumnIndex(MediaStore.Images.Media._ID)
val imageId = mCursor.getInt(columnIndex)
val currentImageUri = Uri.withAppendedPath(uri, imageId.toString())
imageUris.add(currentImageUri)
}
mCursor?.close()
return imageUris
}
and then i ask for the permission in onViewCreated() of my fragment like this:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding = FragmentMainBinding.bind(view)
when {
isStoragePermissionGranted -> {
binding.recyclerView.adapter = RecyclerViewAdapter(getImageUris())
}
shouldShowRequestPermissionRationale -> {
Toast.makeText(mainActivity, "Please grant storage permission", Toast.LENGTH_SHORT).show()
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), STORAGE_PERMISSION_REQUEST_CODE)
}
else -> {
Toast.makeText(mainActivity, "Permission not granted. Images cannot be shown.", Toast.LENGTH_SHORT).show()
}
}
}
I expect this to ask for the storage permission as soon as the app is opened (and my fragment is created) and then it should load all the images on the phone in my recycler view (I am using glide). But it doesn't work the way its expected to, instead the
"Permission not granted. Images cannot be shown."
toast message is shown
For a quick workaround, you can add this in the manifest file under <application>
android:requestLegacyExternalStorage="true"
Read about the storage update for Android 11 here
The problem was here as noted by #blackapps
shouldShowRequestPermissionRationale -> {
Toast.makeText(mainActivity, "Please grant storage permission", Toast.LENGTH_SHORT).show()
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), STORAGE_PERMISSION_REQUEST_CODE)
because shouldShowRequestPermissionRationale is only true when the "deny and don't ask again" option is showing with the permission pop up and that option only appears after the first time the permission has been asked for (which never happens since in order for that to happen, shouldShowRequestPermissionRationale needs to be true).
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
use above permission and in application write below code:
<application
android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true"/

Get current Wifi SSID Android 10

I try to get my currend Wifi SSID on Android 10.
Code from Android 9 or lower does not work anymore.
Is there any sample for Android 10.
Regards Hacki
Since API 26 (Android 8 Oreo) you need to obtain the user location permission in order to get the wifi name (SSID), which is why also in Android 9 (API 28), Android 10 (API 29) or Android 11 (API 30) and newer you may get <unknown name> as the SSID returned or 02:00:00:00:00:00.
For that, in AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I will provide some demo code written in Kotlin.
For declaring your permission request success code, we store it in a companion object (Kotlin way for storing constants) inside the class we are testing from (MainActivity in this case) or you may define a class explicitly for constants, which is actually a common practice.
class MainActivity : AppCompatActivity() {
...
companion object {
const val PERMISSION_CODE_ACCEPTED = 1
const val PERMISSION_CODE_NOT_AVAILABLE = 0
}
...
}
In your testing activity:
when(requestLocationPermission()){
MainActivity.PERMISSION_CODE_ACCEPTED -> getWifiSSID()
}
For checking an requesting the permission:
fun requestLocationPermission(): Int {
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
// request permission
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
MainActivity.PERMISSION_CODE_ACCEPTED)
}
} else {
// already granted
return MainActivity.PERMISSION_CODE_ACCEPTED
}
// not available
return MainActivity.PERMISSION_CODE_NOT_AVAILABLE
}
For actually getting the SSID (wifi name):
fun getWifiSSID() {
val mWifiManager: WifiManager = (this.getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager)!!
val info: WifiInfo = mWifiManager.getConnectionInfo()
if (info.getSupplicantState() === SupplicantState.COMPLETED) {
val ssid: String = info.getSSID()
Log.d("wifi name", ssid)
} else {
Log.d("wifi name", "could not obtain the wifi name")
}
}
Tested on the emulator on API 29 (Android 10).
2020-10-04 15:35:28.625 13013-13013/com.example.myapplication D/wifi name: "AndroidWifi"
Set his two permissions requests into your project manifest file:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"\>
Than you have to set Application permission manually by using Settings screen of Android.

Determine whether a permission is present in the manifest with Android 23+

I am creating a library that needs to check runtime permissions. I have got runtime permissions working fine and understand the use cases without issues.
However I would like to confirm that the developer using our library has added the permission to their manifest.
The library is a location based library and the developer can either enter ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION into the manifest and I need to be able to determine which they have used (or both) at runtime.
I though using the package manager to check permission would work however this always seems to fail:
PackageManager pm = getPackageManager();
int granted = pm.checkPermission(
Manifest.permission.ACCESS_COARSE_LOCATION,
getPackageName() );
if (granted == PackageManager.PERMISSION_GRANTED)
{
// Use coarse for runtime requests
}
// granted is always PackageManager.PERMISSION_DENIED
Is there some other way to do this in Android v23+?
Off the cuff, retrieve the PackageInfo via PackageManager and getPackageInfo(getPackageName(), PackageManager.GET_PERMISSIONS). Then, look at the requestedPermissions array in the PackageInfo for all the <uses-permission>-requested permissions.
Thanks to answer of CommonsWare I'm created this method Kotlin to check if SMS permission is present on Manifest
fun hasSmsPermissionInManifest(context: Context): Boolean {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS)
val permissions = packageInfo.requestedPermissions
if (permissions.isNullOrEmpty())
return false
for (perm in permissions) {
if (perm == Manifest.permission.READ_SMS || perm == Manifest.permission.RECEIVE_SMS)
return true
}
return false
}
or
fun Context.hasSmsPermissionInManifest(): Boolean {
val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
val permissions = packageInfo.requestedPermissions
return permissions?.any { perm -> perm == Manifest.permission.READ_SMS || perm == Manifest.permission.RECEIVE_SMS } ?: false
}

Categories

Resources