Android - Camera permissions denied without prompting - android

I was running into issues with the manual process behind requesting permissions (just kept falling into the 'denied' code), so I switched over to using Dexter to simplify. I implemented the following code in onCreate(), and I did a fresh install of the app:
Dexter.withActivity(this)
.withPermission(Manifest.permission.CAMERA)
.withListener(new PermissionListener() {
#Override public void onPermissionGranted(PermissionGrantedResponse response) {
Log.d(TAG, "GRANTED!");
initCamera();
}
#Override public void onPermissionDenied(PermissionDeniedResponse response) {
Log.d(TAG, "DENIED!");
}
#Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
Log.d(TAG, "PERMISSION RATIONAL SHOULD BE SHOWN!");
}
}).check();
It immediately falls into the "DENIED!" log, and it never even prompts me. I tried this particular code to attempt multiple permissions (which is ultimately what I need to do):
Dexter.withActivity(activity)
.withPermissions(Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
Log.d(TAG, "Accepted: " + report.getGrantedPermissionResponses().size() + " | Denied: " + report.getDeniedPermissionResponses().get(0).getPermissionName());
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
Log.d(TAG, "continuing permissions request..");
token.continuePermissionRequest();
}
})
.check();
It prompts for permissions to Record Audio, then it asks about Access to photos/media/files on the device (it never asks about Camera). Then once that's done, it prints the log: "Accepted 3 | Denied: android.permission.CAMERA". It denies it without even prompting me again.
My Manifest is set properly to have CAMERA in the proper place (outside of the 'application' tag). See below for reference:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.app">
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
etc..
Odd thing is that when I go into Settings > Applications > MyApp, the Camera option is not even displayed in there.
I don't think it's an issue with Dexter, since it's doing basically the same thing when I set it up manually (and I confirmed that it's definitely setup properly in that case after looking at a few top S.O. posts).
Any thoughts on what the issue could be here? FYI - I'm using a Galaxy S6, OS 6.0.2. The other users experiencing this seem to be other devices with 6.0+ OS. Thanks in advance!
EDIT:
Testing various devices, it works on some and does not work on some:
Moto X (OS 5.0) - Broken
Nexus 5 (OS 7.0) - Works
Samsung S6 (OS 6.0.1) - Broken
Broken Moto X (OS 6.0) - Works
Doesn't seem to be a solid pattern.. Definitely strange. I also started a brand new project and ran the same code - worked fine and allowed access to my camera. So it doesn't appear to be fully device-specific..

The issue with this turned out to be a third-party library, which had this line in their Manifest, overriding our own permission:
<uses-permission android:name="android.permission.CAMERA" tools:node="remove" />
The solution was either to manually import their project as a module (rather than use gradle), and then comment out that line, OR more simple - you can add "tools:node="replace"" to the end of the main project's CAMERA permission line, and it works fine after that; no need to import the project with the latter approach.

What you need is native runtime permissions not dexter, Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.YOUR_PERMISSION);
then what you need is to request a certain permission if that check is false,
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.YOUR_PERMISSION},
MY_PERMISSION_CODE);
Bare in ind that you need to as well declare them also in the manifest, based on what you have shown still that was already done. For more information.

Related

Not seeing always allow in android location permission

I have been trying to use an react native ble librairie (react-native-ble-manager). In order to use this the user have to allow location permission (as explain in the documentation android.permission.ACCESS_COARSE_LOCATION and android.permission.ACCESS_FINE_LOCATION if android API >= 29.
I request the autorisation as their example with:
(PermissionsAndroid is from the react-native librairie) :
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
if (result) {
console.log("Permission is OK");
} else {
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
if (result) {
console.log("User accept");
} else {
console.log("User refuse");
}
});
}
});
}
On my device the pop-up ask me for the autorisation with only two choices :
Only when the application is running
Refuse
But with their example I have 3 choices the two others and "always authorise"
And for some reason I'm not able to scan peripheral if I don't always approve (I have been able to change to always for my application by going in the settings of it).
Part of my android manifest (android/app/src/main) (as you can see I have background_location)
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
I'm sure I'm missing an obvious thing but I can't see what..
In advance thank you :)
For those having the same issue : my phone has android 11 so it can't be directly requested in the pop-up.
You have to indicate to your user how to change the permission
Source : https://developer.android.com/training/location/permissions

Checking for permissions always returns "denied". React Native

During the debugging process of React Native application on a physical device (Android) when I check for the location permission it's always blocked, even though I granted the permission in the settings. I have to note that I haven't been able to request the "ask for permission" window previously, so I couldn't block it in any way. Also, I tried to delete and let the app to be installed again.
Here's the code where I check for location permission (I tried others too). There I use react-native-permissions however, the behaviour is the same if I use PermissionsAndroid from react-native.
import {check, PERMISSIONS, request, RESULTS, openSettings} from "react-native-permissions";
async function checkPermissions() {
let response = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION); // <-- always blocked
let isPermissionsGranted = false;
if (response === RESULTS.GRANTED) {
isPermissionsGranted = true;
} else if (response === RESULTS.DENIED) {
response = request(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION, {
title: "FreeLine requires permission",
message: "FreeLine needs access to your location so you can see your position",
buttonPositive: "Ok",
buttonNegative: "Don't show my position",
});
if (response === RESULTS.GRANTED) {
isPermissionsGranted = true;
} else if (response === RESULTS.DENIED) {
await openSettings();
}
}
return isPermissionsGranted;
}
I haven't found any information that'd explain that. I thought that it's possible that during debugging I can't request for permission.
In the end, I found the root of the problem. The funniest thing it isn't connected with my code in any way. The problem was caused by the manifest, to be more precise by rules I included.
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-feature android:name="android.permission.BLUETOOTH" android:required="true"/>
<!-- Only foreground ble access -->
<uses-feature android:name="android.permission.ACCESS_FINE_LOCATION" android:required="true"/>
As you can see from the snippet above, I used use-feature. Here what the docs say about it:
Google Play uses the elements declared in your app manifest to filter your app from devices that do not meet its hardware and software feature requirements.
In addition to the rules above, I have to add uses-permission, like that:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Android ACTIVITY RECOGNITION permission missing

I am targeting SDK 29, and activity transition API works perfectly on devices running 29 (ie Android 10). According to the docs, if you are targeting SDK 29, but running on a lower SDK, the permission should be granted automatically.
I have tried both, separately and together
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_REC‌​OGNITION"/>
I can't ask for the permission in a pop-up ( nothing happens). When I try to register the Transitions API on phones < Andorid 10, I get the error:
com.google.android.gms.common.api.b: 10: SecurityException: Activity detection usage requires the ACTIVITY_RECOGNITION permission
If I set the target SDK to 28, everything works perfectly on all phones, but I need to target 29 for other reasons. I am pulling my hair out.
To be clear, it works perfectly on Android 10, just not below. Further code for clarification:
public void askForActivityPermission(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Log.d(TAG, "askForActivityPermission: q or greater");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, PERMISSION_REQUEST_ACTIVITY_RECOGNITION);
} else {
Log.d(TAG, "askForActivityPermission: less than q");
moveNextStep();
}
}
#Override
public void onRequestPermissionsResult(
int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
String permissionResult = "Request code: " + requestCode + ", Permissions: " +
Arrays.toString(permissions) + ", Results: " + Arrays.toString(grantResults);
Log.d(TAG, "onRequestPermissionsResult(): " + permissionResult);
if (requestCode == PERMISSION_REQUEST_ACTIVITY_RECOGNITION) {
Log.d(TAG, "onRequestPermissionsResult: permission granted?");
moveNextStep();
}
There were some updates in API Level 29.
1.Add the permission to the manifest file.
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
2.Check if the permission is granted:
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.ACTIVITY_RECOGNITION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
}
3.If permission isn't already granted, request the permission:
ActivityCompat.requestPermissions(thisActivity,
arrayOf(Manifest.permission.ACTIVITY_RECOGNITION),
MY_PERMISSIONS_REQUEST_ACTIVITY_RECOGNITION);
Here are some useful docs.
https://developer.android.com/about/versions/10/privacy/changes#physical-activity-recognition
https://developers.google.com/fit/android/authorization
Ok, i have got it working, but it makes no sense, what so ever, like none.
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_REC‌​OGNITION" />
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
The top one does not work, the bottom one does. Can anyone tell me why?
I have tried all the suggested solutions, but none of them worked out. I've tried all combinations of com.google.android.gms.permission.ACTIVITY_REC‌​OGNITION and com.google.android.gms.permission.ACTIVITY_RECOGNITION
with minSdkVersion 26 and targetSdkVersion 30
using an Android 9 (API 28) Wear OS emulator.

How can I modify BluetoothleGatt to enable BLE device scanning on Android 6.0?

I am new to Android App developing and BLE, and I am learning these using the sample code BluetoothLeGatt [The one I imported from Android Studio]. The code works fine on my tablet (Android 5.0), but the scan activity does not return any BLE devices on Android 6.0. The error message I got is shown below.
07-19 12:41:39.615 7617-7642/? W/Binder: Caught a RuntimeException from the binder stub implementation.
java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:772)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:331)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)
at android.os.Binder.execTransact(Binder.java:458)
I looked at the post Bluetooth Low Energy startScan on Android 6.0 does not find devices and the official page Requesting Permissions at Run Time, but I still don't really know how to modify my code.
I did add the permissions of GPS, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, and I turned on the Location Service on my tablet.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature android:name="android.hardware.location.gps" />
But the App still cannot return any BLE devices. Then, when I try to add the following block of code to my App (from Requesting Permissions at Run Time ), there is always an error on checkSelfPermission [Cannot resolve symbol 'checkSelfPermission']. But I did import import android.support.v4.content.ContextCompat;
Can someone help me with this? Also, is there a simpler answer to the question how to make DeviceScanActivity work? I don't really know where to put the blocks of the code from Requesting Permissions at Run Time to my code :( I know this is a really stupid question, but I am really new to this field. Please help me!
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
EDIT
The following is my dependencies block.
dependencies {
compile "com.android.support:support-v4:25.3.1"
compile "com.android.support:support-v13:25.3.1"
compile "com.android.support:cardview-v7:25.3.1"
compile "com.android.support:appcompat-v7:25.3.1"
}
Thank you everyone for your responses and help! I've just solved my case!
What I did is that besides adding the permissions in AndroidManifest.xml, I added the following code to my onCreate method in DeviceScanActivity, and the reference I used is Requesting Permissions at Run Time. Also, I just randomly assigned a number to MY_PERMISSIONS_REQUEST_LOCATION.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
mHandler = new Handler();
//Check for permissions
int permissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_CALENDAR);
Log.e(TAG, "Permission Status: " +permissionCheck );
//***********************************************************
//
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
{
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_COARSE_LOCATION))
{
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
}
else
{
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
}
......//The rest of code
}
When I first added the above code, there is a pop-up window coming up on my tablet asking me for permissions, and I clicked "allow."
Then, I am able to scan my ble devices.
BTW, it only asks for my permission once. When I clicked "Run Application" later (after slight modifications of my code), it didn't ask for my permission again.
Do you add those all permissions:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
It works fine on android 6.0

Application that can get Location and runs on android 4.0.3+

For android versions less than 6 just adding these permission requests to the manifest works:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
But for android version 6 I need explicitly request permission too to get the location:
requestPermissions(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION}, 1340);
The problem is that If I add the above code the App works only on android 6 and fails to run on lower versions as requestPermissions does not exist on lower versions. and If I remove it I won't be able to get the location on android 6.
What can I do that my app be able to get the location on android 4.0.3+
You can check the API level of the phone that is running your app like this:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//later than 4.x - so here you can run the code
//ideally you want to make this call in a helper method which you then annotate with the #TargetApi
requestPermissions(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION}, 1340);
}
else{
//nothing to do in your case ?
}
You can also use #TargetApi(Build.VERSION_CODES.LOLLIPOP) in the methods where you want to make "Lollipop+" calls.

Categories

Resources