I have set in my android manifest the following permissions:
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="27" />
<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_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application android:label="MyApp" android:icon="#drawable/icon">
But if a take a look at the app settings on my phone, the app has no permissions set. Should the app not asking me if I want give this grant on installation?
Thanks
Android permissions work like this :
If your permission is normal permission it will be auto-granted.
If we are talking about dangerous permissions it goes like this :
If the device API level is <= 22 / targetSdkVersion is 22 or lower:
In that case, the user will be asked (by the system) in the install time to grant all the dangerous permissions for the app.
If the device API level is > 22 and targetSdkVersion is above 22:
The user will not accept dangerous permissions at install time.
You must ask the user to grant access to the dangerous permissions at runtime - when you do ask your user to give access to those permissions on run time he will see system dialog
that asks him to accept or decline the permissions.
So if your app did not ask permission at install time it may have higher API level.
For more information, you can check this
Do it like this.
Write a function to add the needed permission to a list
private boolean addPermission(List<String> permissionsList, String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
return shouldShowRequestPermissionRationale(permission);
}
}
return true;
}
Add a function to create the list
private void requestPermissions() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, ACCESS_FINE_LOCATION))
permissionsNeeded.add("Location");
if (!addPermission(permissionsList, Manifest.permission.READ_EXTERNAL_STORAGE))
permissionsNeeded.add("Read");
if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE))
permissionsNeeded.add("Write");
// add all your permissions needed except normal permissions
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
StringBuilder message = new StringBuilder("You need to grant access to: \n- " + permissionsNeeded.get(0));
for (int i = 1; i < permissionsNeeded.size(); i++)
message.append("\n- ").append(permissionsNeeded.get(i));
showMessageOKCancel(message.toString(),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
}
}
Then, override the activity function onRequestPermissionsResult
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Test ACCESS_FINE_LOCATION (if needed) or other permission
if (perms.get(ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Permission Denied
Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
On your MainActivity in onCreatecall requestPermissions();
Related
I am trying to request WRITE_EXTERNAL_STORAGE permission on Android 10. I do that using the following code:
ArrayList<String> permissions = new ArrayList<>();
if (this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (this.checkSelfPermission(ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
this.checkSelfPermission(ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissions.size() > 0) requestPermissions(permissions.toArray(new String[0]), PERMISSION_REQUEST_FINE_LOCATION);
Here is the manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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" />
All other permissions work except WRITE_EXTERNAL_STORAGE. When I try to request it, it does not display any dialog for confirming permission, but it simply denies it. Why and how can I fix it?
I have discovered the solution, however the cause of the problem is still a mystery to me. If anyone has an explination, it would be greatly appreciated. Basically my issue is a duplicate of this issue. All I had to do is to change the following line from
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
to
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/>
What does tools:node="replace" do?
You can handle requested permission using this method (works with android 10), Here is the documentation.
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
switch (requestCode) {
case PERMISSION_REQUEST_ID_STORAGE:
// permisstion granted by user
break;
}
} else {
switch (requestCode) {
case PERMISSION_REQUEST_ID_STORAGE:
// permission denied by user
break;
}
}
}
You can use Android Runtime Permission Library by nabinbhandari
in you build.gradle app module file write this
//Android Runtime Permission Library
implementation 'com.nabinbhandari.android:permissions:3.8'
In your Manifest file write
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
and in Activity declare these variables
String[] permissions = new String[]{READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE};
String rationale = "Please provide storage permission to proceed ...";
And in your onCreate() Method write this
Permissions.Options options = new Permissions.Options()
.setRationaleDialogTitle("Info")
.setSettingsDialogTitle("Warning");
Permissions.check(MainActivity.this, permissions, rationale, options, new PermissionHandler() {
#Override
public void onGranted() {
// do your task.
Toast.makeText(MainActivity.this, "Permissions granted", Toast.LENGTH_SHORT).show();
}
#Override
public void onDenied(Context context, ArrayList<String> deniedPermissions) {
// permission denied
Toast.makeText(MainActivity.this, "Permissions denied", Toast.LENGTH_SHORT).show();
}
});
I am developing an Android application that has its own video recorder feature. For that I need to request RECORD_AUDIO permission from the user. But when I request the permission, it is not showing the prompt to get the permission from the user.
This is my function that checks if the app needs to request permission and it does automatically if required.
private boolean isRecordAudioPermissionGranted()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED) {
// put your code for Version>=Marshmallow
return true;
} else {
if (shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)) {
Toast.makeText(this,
"App required access to audio", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO
},AUDIO_RECORD_REQUEST_CODE);
return false;
}
} else {
// put your code for Version < Marshmallow
return true;
}
}
In the onCreate of the Activity, I call the function like this.
if(!isRecordAudioPermissionGranted())
{
Toast.makeText(getApplicationContext(), "Need to request permission", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), "No need to request permission", Toast.LENGTH_SHORT).show();
}
The app is saying that it needs to request permission, but it is just not prompting the request permission dialog. What is wrong with my code?
This are the permissions I added and use in the manifest file.
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.Manifest.permission.RECORD_AUDIO"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-feature android:name="android.hardware.camera.front"/>
<uses-feature android:name="android.hardware.camera.front.autofocus"/>
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true"/>
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true"/>
<uses-feature android:name="android.software.vr.mode" android:required="true"/>
<uses-feature android:name="android.hardware.vr.high_performance" android:required="true"/>
For RECORD_AUDIO permission, correct permission string is
android.permission.RECORD_AUDIO
In your manifest you are using
<uses-permission android:name="android.Manifest.permission.RECORD_AUDIO"/>
which in incorrect and it must be
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
add this in manifest file
in java
//Requesting run-time permissions
//Create placeholder for user's consent to record_audio permission.
//This will be used in handling callback
private final int MY_PERMISSIONS_RECORD_AUDIO = 1;
private void requestAudioPermissions() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
//When permission is not granted by user, show them message why this permission is needed.
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.RECORD_AUDIO)) {
Toast.makeText(this, "Please grant permissions to record audio", Toast.LENGTH_LONG).show();
//Give user option to still opt-in the permissions
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
MY_PERMISSIONS_RECORD_AUDIO);
} else {
// Show user dialog to grant permission to record audio
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
MY_PERMISSIONS_RECORD_AUDIO);
}
}
//If permission is granted, then go ahead recording audio
else if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
//Go ahead with recording audio now
recordAudio();
}
}
//Handling callback
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_RECORD_AUDIO: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
recordAudio();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Permissions Denied to record audio", Toast.LENGTH_LONG).show();
}
return;
}
}
}
I add bluetooth to my app but am running into the following problem. When I do the code:
BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Device doesnt Support Bluetooth",Toast.LENGTH_SHORT).show();
}
if(!bluetoothAdapter.isEnabled()) {
Intent enableAdapter = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableAdapter, 0);
}
The error is on the following line:
if(!bluetoothAdapter.isEnabled())
Error:
Missing permissions required by BluetoothAdapter.isEnabled :android.permissions.BLUETOOTH
I added the following permissions to the android manifest file:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<permission android:name="android.permission.BLUETOOTH" android:label="BLUETOOTH" />
<permission android:name="android.permission.BLUETOOTH_ADMIN" />
but am still getting the same issue. Do you know what I did wrong?
You only need <uses-permission> tag since you are using a permission. You don't need <permissions> tag since this is not your custom permission.
Maybe you have placed <uses-permission> tag in the wrong element in manifest, but I cannot say anything else with the information you provided
Since your bluetoothAdapter can be null, either add to second IF null pointer check, or add a RETURN in first IF
It is also nice to have <uses-feature> tag
Let's say you have a button and then you click on it, Bluetooth needs to turn on. Here's a quick example how you would do it for Android 6.0 and above.
First, declare this variable in your Activity/Fragment:
public static final int PERMISSION_ASK = 1001;
Now, let's say this buttons is going to enable the bluetooth.
setOnClickListener:
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(isBluetoothPermissionGranted()) {
// app already has required permissions
// do some task here
} else {
// app does not have permission yet.
// ask for permissions
askForBluetoothPermissions();
}
} else {
// Android version below 6.0, no need to check or ask for permission
// do some task here
}
}
});
Checking if application already has the required permission:
#RequiresApi(api = Build.VERSION_CODES.M)
private boolean isBluetoothPermissionGranted() {
boolean granted = false;
int bluetoothGranted = checkSelfPermission(Manifest.permission.BLUETOOTH);
int bluetoothAdminGranted = checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN);
if(bluetoothGranted == PackageManager.PERMISSION_GRANTED &&
bluetoothAdminGranted == PackageManager.PERMISSION_GRANTED) {
granted = true;
}
return granted;
}
If required permission is not granted, here's how you would ask for it:
#RequiresApi(api = Build.VERSION_CODES.M)
private void askForBluetoothPermissions() {
String[] permissions = new String[] {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN
};
requestPermissions(permissions, PERMISSION_ASK);
}
And finally, here's how you would confirm if the user granted you the permission(s) or not:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_ASK:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// all requested permissions were granted
// perform your task here
} else {
// permissions not granted
// DO NOT PERFORM THE TASK, it will fail/crash
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
Hope this helps
For Android 6.0 and above you must add the following to manifest file
<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" />
<permission android:name="android.permission.BLUETOOTH" android:label="BLUETOOTH" />
<permission android:name="android.permission.BLUETOOTH_ADMIN" />
<permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Here is my manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
This is all I needed for my project but I need it in code, not manually in app settings.
To use the new permission model in Marshmallow, you need to both specify your permissions in the manifest (as you did) AND request the permission at runtime. Only permissions that are considered as "dangerous" require the runtime request. Dangerous is defined as:
A higher-risk permission that would give a requesting application
access to private user data or control over the device that can
negatively impact the user. Because this type of permission introduces
potential risk, the system may not automatically grant it to the
requesting application. For example, any dangerous permissions
requested by an application may be displayed to the user and require
confirmation before proceeding, or some other approach may be taken to
avoid the user automatically allowing the use of such facilities.
From: https://developer.android.com/guide/topics/manifest/permission-element.html
Here's an example of code that checks if you need to request the permission. (Remember, even if the user grants your permission request, they can later revoke it in App Settings, so you need to check each time you need it.)
private final int REQUEST_PERMISSION_ACCESS_FINE_LOCATION=1;
private void requestAccessLocationPermission() {
int permissionCheck = ContextCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
showExplanation("Permission Needed", "Rationale", Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_PERMISSION_ACCESS_FINE_LOCATION);
} else {
requestPermission(Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_PERMISSION_ACCESS_FINE_LOCATION);
}
} else {
Toast.makeText(MainActivity.this, "Permission (already) Granted!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onRequestPermissionsResult(
int requestCode,
String permissions[],
int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_ACCESS_FINE_LOCATION:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this, "Permission Granted!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Permission Denied!", Toast.LENGTH_SHORT).show();
}
}
}
here is my java code.
public static void checkSinglePermissionCompat(final Activity activity,
ActionNeedsPermission action, final String permission,
final int permissionCode, String message) {
int hasPermission = ActivityCompat.checkSelfPermission(activity, permission);
if (hasPermission == PackageManager.PERMISSION_GRANTED) {
action.performAction();
} else {
if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
showRationaleDialog(activity, message,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
ActivityCompat.requestPermissions(activity, new String[]{permission}, permissionCode);
}
});
} else {
ActivityCompat.requestPermissions(activity, new String[]{permission}, permissionCode);
}
}
}
my gradle file
android {
compileSdkVersion "android-MNC"
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion "MNC"
targetSdkVersion "MNC"
}
}
and my manifest file
<uses-permission-sdk-m android:name="android.permission.CAMERA"/>
<uses-permission-sdk-m android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission-sdk-m android:name="android.permission.RECORD_AUDIO" />
<uses-permission-sdk-m android:name="android.permission.SEND_SMS" />
it just callback permission denied, did not show the system permission request dialog. anyone could help me? thx
Refer this sample Google sample code
<!-- Note that all required permissions are declared here in the Android manifest.
On Android M and above, use of these permissions is only requested at run time. -->
**<uses-permission android:name="android.permission.CAMERA"/>**
<!-- The following permissions are only requested if the device is on M or above.
On older platforms these permissions are not requested and will not be available. -->
**<uses-permission-sdk-m android:name="android.permission.READ_CONTACTS" />
<uses-permission-sdk-m android:name="android.permission.WRITE_CONTACTS" />**