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_RECOGNITION"/>
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_RECOGNITION" />
<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_RECOGNITION and com.google.android.gms.permission.ACTIVITY_RECOGNITION
with minSdkVersion 26 and targetSdkVersion 30
using an Android 9 (API 28) Wear OS emulator.
Related
I've looked through this guide for android 13 push notifications
https://developer.android.com/about/versions/13/changes/notification-permission#user-choice
And I've looked at the guide for requesting permissions
https://developer.android.com/training/permissions/requesting#java
I've updated my compile and target to api 32.
Here is my code so far (in progress). Right now I'm just trying to get the notification prompt to show up.
if (Build.VERSION.SDK_INT >= 32) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NOTIFICATION_POLICY) == PackageManager.PERMISSION_GRANTED)
return;
ActivityResultLauncher<String> launcher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(), isGranted -> {
}
);
launcher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
The problem I have is I get an error cannot find symbol variable POST_NOTIFICATIONS.
What is the proper manifest permission for push notifications?
Maybe I'm a bit late to the party, I know... But I hope this can help others at least. You need to use compileSdkVersion 33 in your gradle file at the Module level. Then you'll be allowed to use the POST_NOTIFICATIONS permission without any issue.
Android 13 (API level 33) and higher supports a runtime permission for sending non-exempt (including Foreground Services (FGS)) notifications from an app: POST_NOTIFICATIONS. This change helps users focus on the notifications that are most important to them.
reference here
So you need to add this permission to AndroidManifest.xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
You need to follow few steps, add post notifications permission in manifest
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
then in your controller as for run time permission like generally we ask:
if (Build.VERSION.SDK_INT >= 33) {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.POST_NOTIFICATIONS},101);
}
else {
createChannel();
}
}
Then Need to handle permission result as usual
How to add run time permission for notification permission in android studio,
Apps targeting Android 13 will now need to request notification permission from the user before posting notifications,”
Behavior changes: Apps targeting Android 13 or higher
https://developer.android.com/about/versions/13/behavior-changes-13
Add on manifest: uses-permission android: name="android.permission.POST_NOTIFICATIONS
and
Add in MainActivity after onCreate:
if (ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(this, new String[]{POST_NOTIFICATIONS}, 1);
}
I've created a sample Wear OS app, which should discover BLE devices, but my code requires Bluetooth permission. When I put these lines in manifest:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
corresponding permission is not displayed in settings/apps/permissions and every permission request does nothing. By the way, my BLE-devices (a speaker and a esp-32) is not shown in settings/Bluetooth also.
How can I grant Bluetooth permissions for my app or how can I connect BLE device to my watch?
upd:
I tried these:
if (checkSelfPermission(Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH), 1001)
}
if (checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH_CONNECT), 1001)
}
if (checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH_SCAN), 1001)
}
if (checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.BLUETOOTH_ADMIN), 1001)
}
But dialogs windows still are not displayed
According documentation, you need particular permissions in based of the target Android API version.
If your app targets Android 11 (API level 30) or lower, declare the following permissions in your app's manifest file:
BLUETOOTH is necessary to perform any Bluetooth classic or BLE communication, such as requesting a connection, accepting a connection, and transferring data.
ACCESS_FINE_LOCATION is necessary because, on Android 11 and lower, a Bluetooth scan could potentially be used to gather information about the location of the user.
If your app targets Android 9 (API level 28) or lower, you can declare the ACCESS_COARSE_LOCATION permission instead of the ACCESS_FINE_LOCATION permission.
In order to perform a scan to discover BLE devices the app must require explicitaly to the user the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission also to be declared in the AndroidManifest.xml.
In my project (WearOS API version 28) I used this code in the onCreate function of MainActivity class
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
1);
}
And I overrided the onRequestPermissionsResult function
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case 1:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Logger.d("MainActivity","Permission approved");
} else {
Logger.d("MainActivity","Error getting permission");
}
return;
}
}
This works for me, I hope would help you
there are some permissions like camera, bluetooth which need to be asked first and then manually provided. use this in the activity that loads first in your app.
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf<String>(Manifest.permission.CAMERA), 1001);
} //ask camera permissions
make sure to do required changes.
According to "developer.android.com"
If the app targets Android 8.0 (API level 26), the system grants only
READ_EXTERNAL_STORAGE at that time; however, if the app later requests
WRITE_EXTERNAL_STORAGE, the system immediately grants that privilege
without prompting the user.
Now, I have the READ_EXTERNAL_STORAGE and I'm requesting the DownloadManager to download a file in the Public Download folder
downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mAttachmentItem.getFilename());
Unfortunately, I got
E/UncaughtException: java.lang.IllegalStateException: Unable to create directory: /storage/emulated/0/data/user/0/com.abc.cba/files
at android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.java:699)
I have declared both of permissions in the Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Read permission is already Granted and in Runtime I'm requesting Write permission, the system doesn't prompt any message or dialog, it's always Denied(Not Granted) in "onRequestPermissionsResult"
public static boolean isPermissionsToAccessStorageAreGranted(Context context, Activity activity) {
ArrayList<String> permissions = new ArrayList<>();
if (!PermissionUtil.checkPermissions(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!permissions.isEmpty()) {
String[] permissionsList = permissions.toArray(new String[permissions.size()]);
PermissionUtil.requestPermissions(activity, permissionsList,
PermissionUtil.REQUESTCODE_ACCESS_STORAGE);
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==REQUESTCODE_ACCESS_STORAGE && grantResults[0]== PackageManager.PERMISSION_GRANTED){
/* downloadFile(); */
}
}
I'm trying to grant those two permissions via ADB, it shows me an error:
adb shell pm grant com.abc.cba
android.permission.WRITE_EXTERNAL_STORAGE
Operation not allowed: java.lang.SecurityException: Package com.abc.cbs
has not requested permission android.permission.WRITE_EXTERNAL_STORAGE
adb shell pm grant com.abc.cba
android.permission.READ_EXTERNAL_STORAGE
Operation not allowed: java.lang.SecurityException: Can't change
android.permission.READ_EXTERNAL_STORAGE. It is required by the
application
Actually, It was an external problem. One of App Libs I'm using request the WRITE_EXTERNAL_PERMISSION with android:maxSdkVersion. So when merging with my Manifest it will remove the permission for the whole application.
The Solution is to add:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/>
You are correct in adding the permissions to the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
For versions of Lollipop and higher, you need to also request the permissions at runtime. To solve this problem, I created a new method requestAppPermission that I call when the main activity is created. This method runs only for Lollipop and higher, and returns early otherwise:
private void requestAppPermissions() {
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
if (hasReadPermissions() && hasWritePermissions()) {
return;
}
ActivityCompat.requestPermissions(this,
new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, REQUEST_WRITE_STORAGE_REQUEST_CODE); // your request code
}
private boolean hasReadPermissions() {
return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}
private boolean hasWritePermissions() {
return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}
I call this method in the activity's onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other things
requestAppPermissions();
}
On first load, this will prompt the user to accept permissions.
Then, before you run any code that needs to read and write to storage, you can check these permissions, either by storing the values or running those checks again using methods hasReadPermissions() and hasWritePermissions() defined above.
UPDATE: See this answer for a better solution
EDIT: This is not a solution, just a quick workaround.
If you get permission denied error even when the permissions are granted and you already implemented permission checks,
make sure you're not targetting api level 29:
Change targetSdkVersion and compilesdkversion from 29 to 28 or any other lower level.
For Oreo,
you need to explicitly do a READ_EXTERNAL_STORAGE request (by code) even if you have already requested and is granted the WRITE_EXTERNAL_STORAGE permission, and vis versa.
prior to this, READ_EXTERNAL_STORAGE is automatically granted when WRITE_EXTERNAL_STORAGE is granted.
so what you need to do, is to
1) ask for WRITE permission in your codes.
2) when user grants the WRITE permission, ask again for READ permission - this will be automatically granted (you will get an exception if you do not ask for a READ explicitly)
The changes for Oreo doesn't make much sense to me (no idea why do we need to ask for a permission that is automatically granted), but that is what it is.
https://developer.android.com/about/versions/oreo/android-8.0-changes.html#rmp
You have to grant permissions at runtime on Marshmallow or higher.
Sample snippet :
private static final int REQUEST_WRITE_STORAGE = 112;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean hasPermission = (ContextCompat.checkSelfPermission(getBaseContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
ActivityCompat.requestPermissions(SplashScreen.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.INTERNET
},
REQUEST_WRITE_STORAGE);
}else{ startMainActivity(); }
}
Hope it helps.
Use this
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
instead of
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE/>"
Some of your third party libraries are override maxSdkVersion like com.vungle:publisher-sdk-android, to finding them just check the Merged Manifest below of your manifest screen. see this
For SDK 29 and Later
If you are still having issue to accessing external storage, consider using android:requestLegacyExternalStorage="true" in your <application> tag of your manifest.
Just a notice: on Android P I had to show a terminate dialog box to user asking to restart the app because even after all written above app couldn't read external storage, only after restart. Seriously, those guys in google makes Android better each time. 6, 8, and now so much troubles with 9, one more such stupid update and I will go to iOS :)
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.
I have a problem when running my app on Android OS 4.0 and requesting READ_EXTERNAL_STORAGE permission with:
ActivityCompat.requestPermissions(ctx, requestedPermissions, requestCode);
I always get on the callback
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
grantResults != PackageManager.PERMISSION_GRANTED
Checking the permission with ActivityCompat.checkSelfPermission is always returning permissionDenied.
It works well on OS 6.0 by requesting the permission with system dialog.
Android OS 4.x excepted the 4.0 the permission is always granted.
OS 4.0 the other permissions (Camera,Calendar,Contact,Phone) are behaving well except the READ_EXTERNAL_STORAGE causing this issue.
Maybe an OS issue?
What ActivityCompat.requestPermissions() does is:
call through to the real requestPermissions() if you are on Android 6.0+, or
use PackageManager to see if you hold the requested permissions on older versions of Android
The problem with READ_EXTERNAL_STORAGE is that it was added in API Level 16 (Android 4.1). You cannot hold it on older versions of Android than that, for the simple reason that it did not exist.
Either:
Set your minSdkVersion to 16, or
Put your own logic in to handle this case, recognizing that READ_EXTERNAL_STORAGE is irrelevant prior to API Level 16
I discovered this issue when dealing with FOREGROUND_SERVICE on Android 8.0. My solution unfortunately depends on the exception handling, but it does not require dealing with the API level the permission is supported from. You can check if permission exists on current API level with this method:
private boolean permissionExistsOnCurrentApiLevel(String permission) {
try {
getPackageManager().getPermissionInfo(permission, PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return true;
}
With this method you can implement you own version of ContextCompat.checkSelfPermission where all non-existing permission are automatically considered to be granted:
private int myCheckSelfPermission(#NonNull Context context, #NonNull String permission) {
if(!permissionExistsOnCurrentApiLevel(permission)) {
return PackageManager.PERMISSION_GRANTED;
}
return ContextCompat.checkSelfPermission(this, permission);
}