I'm trying to request the ability to read contacts in an app, and have followed several tutorials. All of these use nearly the same code for this process. Below is the code in my MainActivity.java file, that should request permission.
private void checkContactPermissions()
{
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Contacts permission NOT granted");
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
else
{
Log.i(TAG, "Contacts permission granted");
readContacts();
}
}
My manifest.xml also includes the line:
<uses-permission android:name="android.permission.READ_CONTACTS" />
When the app is run, either on emulator or physical debugging device, it does not ask for permission, however the log states that the permission was granted. I have confirmed the permission is off by going to the settings and checking it was turned off. What else would be causing the app to perform as if permissions were granted.
Try this,
private Context mContext=YourActivity.this;
private static final int REQUEST = 112;
if (Build.VERSION.SDK_INT >= 23) {
String[] PERMISSIONS = {android.Manifest.permission.READ_CONTACTS};
if (!hasPermissions(mContext, PERMISSIONS)) {
ActivityCompat.requestPermissions((Activity) mContext, PERMISSIONS, REQUEST );
} else {
readContacts();
}
} else {
readContacts();
}
get Permissions Result
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readContacts();
} else {
Toast.makeText(mContext, "The app was not allowed to read your contact", Toast.LENGTH_LONG).show();
}
}
}
}
check permissions for marshmallow
private static boolean hasPermissions(Context context, String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
Manifest
<uses-permission android:name="android.permission.READ_CONTACTS" />
I use RxPermission for permissions to make my code ultimately short.
First add these permissions (or one you need) in your manifest.xml.
<uses-permission android:name="android.permission.READ_CONTACTS" />
Then ask run time permission from user in your activity.
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.READ_CONTACTS) // ask single or multiple permission once
.subscribe(granted -> {
if (granted) {
// All requested permissions are granted
} else {
// At least one permission is denied
}
});
add this library in your build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}
Isn't this easy?
As Divyesh Patel pointed out, I had the boolean statemetns mixed up, it should be
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED)
Rather than
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED)
Important thing for you to note here that these permissions are asked only for devices with version>23 and if you have lower version of android then for only some models like redmi you have to invoke the permissions manually .
Otherwise version<23 generally do not ask for permissions.
If you put in manifest. It will automatically take it, specially when you are installing app over usb.
If any device has OS version below <23 or In app manifist file maxtarget version is below <23 then it will not ask permission in runtime because while the app installing on these devices you actually giving permission to all you mentioned.
So the runtime permissions are possible only in the case of device has OS version above 22(Lolipop).
Hope this helpful..
#Rajesh
Related
Any idea how to enable the permission on the app? the permission was disabled by default on Android 13 Emulator. It was working on other emulator, just not Android 13 Emulator. By default, adding Firebase Messaging will add the Manifest.permission.POST_NOTIFICATIONS into the Manifest.
requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS);
auto return isGranted = false
in Manifest:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
This is how to request and check results for runtime for api13
private void request_notification_api13_permission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (this.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.POST_NOTIFICATIONS}, 22);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 22) {
if (grantResults.length > 0)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission granted, perform required code
} else {
// not granted
}
}
}
calling function will be like this:
request_notification_api13_permission();
I cannot make this work, I have an application with a webview that requires permissions to access storage when downloading, I am trying that, when the user rejects permissions, my application tells them how to activate the permission by accessing the application settings.
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getActivity().getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
s
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Permission is granted
myWebView.loadUrl(urlDownload);
} else {
}
return;
}
case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openImageChooserActivity();
} else {
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
myWebView.loadUrl(urlDownload); this code snippet runs without problem when permission is granted from android alert but I can't control it if the user grants the permission from the settings.
Finally, a newbie question, I have seen several examples of similar codes that seem to work, but I do not understand how setResult is handled in the configurations because I do not have access to it, if for example MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101 how is it that android configurations know to put setResult (101) when user activates storage?
I want create new file and write/read app settings. isExternalStorageAvailable() return false and should true. Android emulator external memory = 200mb.
boolean isExternalStorageAvailable() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
return true;
}
return false;
}
Added permissions to manifest file:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
saveButton.setEnabled(false);
System.out.println("Available: "+isExternalStorageAvailable()+", ReadOnly: "+isExternalStorageReadOnly());
}
else {
myExternalFile = new File(getExternalFilesDir(filepath), filename);
}
}
To get all external storage paths this can be used:
File[] extSDCardPaths = null;
try {
extSDCardPaths = ContextCompat.getExternalFilesDirs(ctx, null);
} catch (Exception e) {
// handle
}
for (File f : extSDCardPaths) {
if (Environment.isExternalStorageRemovable(f)) {
// check if anything found
}
}
If extSDCardPaths returns something then ext storage is available.
The above works for > 4.4(KitKat) only
The below hack can be used as fallback for lower OS versions:
String[] fallback = {"/storage/sdcard1/", "/mnt/ext_card/", "/mnt/extSdCard/", "/storage/extsdcard/",
"/mnt/extsdcard/", "/storage/extSdCard/", "/mnt/external_sd", "/storage/MicroSD/",
"/storage/external_SD/", "/storage/ext_sd/", "/storage/removable/sdcard1/", "/mnt/sdcard/external_sd/",
"/storage/ext_sd/", "/mnt/emmc/", "/data/sdext/", "/sdcard/sd/"};
for (String path : fallback) {
if (new File(path).exists()) {
// found an ext. dir
break;
}
}
If your application is targeting and running on marshmallow or above, you must gain permission to read/write to external storage, you must request permission from user explicitly after declaring permission in manifest.
Make sure you have this in your manifest: <uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Check for permission explicitly. If not provided, request it:
public void checkPermissionReadStorage(Activity activity){
if (ContextCompat.checkSelfPermission(activity,
Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Show an expanation 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(activity,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_STORAGE);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
}
Receive permission response:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PermissionManager.MY_PERMISSIONS_REQUEST_READ_STORAGE:
//premission to read storage
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted. Call your storage related code here
} else {
// permission denied.
// Handle permission failed here.
}
return;
// other 'case' lines to check for other
// permissions this app might request
}
}
Code was taken from here
I'm trying to test the Runtime Permissions specifically for Android sdk > 23. But my app is being granted permissions automatically without asking.
Note : I'm using sdk version 24. Here's a snippet of code I'm using:
public void onCalendarClick(View view) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR) == PackageManager
.PERMISSION_DENIED) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.WRITE_CALENDAR)) {
//Display Explanation to the user
//For granting permissions to the app.
}
else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CALENDAR}, CALLBACK_CALENDAR);
}
}
}
#Override
public void onRequestPermissionsResult(int resultCode, String permission[], int grantResults[]) {
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast toast;
switch (resultCode) {
case CALLBACK_CALENDAR : toast = Toast.makeText(this,"Calendar Permission Granted!!",Toast.LENGTH_LONG);
toast.show(); break;
//Other Cases
}
}
}
When I click on Calendar Button, the onCalendarClick() method run, but without asking for any permission, the App directly displays Calendar Permission Granted!! toast. In the App's settings, there are though No Permissions Granted/Requested being displayed.
Am I missing something or doing it the wrong way? Thanks for any help.
So here it is. I found out that for android sdk > 22, though Runtime permissions are added programatically for your application but you still need to declare your app's permission in the AndroidManifest.xml file. So, after adding the code:
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
in the AndroidManifest.xml, the app asks for the permission and it's finally working.
For more information : Android M permission dialog not showing
.Thanks to all for helping me out )
You are missing the order of the code. Check this:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case CALLBACK_CALENDAR: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// calendar-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
There is a little difference, you are asking if the permission is granted even before you know you are talking about CALENDAR permissions. So, you should first check if the current permission response is the one you want, and then check if the permission is granted.
Source: https://developer.android.com/training/permissions/requesting.html
I want to get permissions for ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION in android but for whatever reason it only grants permission for ACCESS_COARSE_LOCATION .
My activity:
final int PERMISSION_ALL = 1;
String[] PERMISSIONS = {ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION};
if(!hasPermissions(this, PERMISSIONS)){
System.out.println("=========================================nottttt========================================================");
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
#Override
public void onRequestPermissionsResult(int requestCode, String PERMISSIONS[], int[] grantResults) {
System.out.println("==================requesttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt");
switch (requestCode) {
case PERMISSION_ALL: {
System.out.println("lengthhhhhhhhhhhhhhhhhhhhhh"+PERMISSIONS.length);
for (int i = 0; i < PERMISSIONS.length; i++) {
String permission = PERMISSIONS[i];
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
System.out.println(permission + "is alreadyyyyyyyyyyyyy grantedddddddddddddddd");
} else {
System.out.println(permission + "is not grantedddddddddddddddd");
}
return;
}
}
}
}
public static boolean hasPermissions(Context context, String[] permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
Android manifest:
<user-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<user-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I start the app, I am prompted to give access to the location, I choose yes , but ACCESS_FINE_LOCATION is not granted.Can somebody help me find the problem?
Once the user granted permission to one of those permissions, the permission for the other will be granted too. You can't have one of them granted and the other not granted.
ACCESS_FINE_LOCATION permission allow app to use GPS and Network location providers. But, Network provider is a coarse location provider. That is why, if you request ACCESS_FINE_LOCATION first, it will request ACCESS_COARSE_LOCATION permission authomatically