storage permissions not being asked - android

I have added to the manifest files these permissions
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
But when the user installs the app the only permission he is being asked and allows is location.
I also want to ask the user for storage permission.How is this possible?

Use runtime permission code where you add the data inside the internal storage. You can use dexture or easy permission lib for this.

Have you tried what the Android documentation points out:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not 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; 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.
}
} else {
// Permission has already been granted
}
https://developer.android.com/training/permissions/requesting#java

For "dangerous" permissions (includes Storage, Location, Camera, Calendar and more), you need to request the user for their permission not at installation, but when it's required.
It's important that you check every time the permission is required, because the user can revoke the permission anytime.
To check for permission (in Kotlin) (in this example it's FINE_LOCATION, change it to whatever permission you need to request):
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) {
//if permission not granted, start function to request permission
//MY_PERMISSIONS_REQUEST is the requestCode, an int > 0
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
MY_PERMISSIONS_REQUEST
)
}
and then then override the onRequestPermissionsResult function:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>, grantResults: IntArray
) {
when (requestCode) {
MY_PERMISSIONS_REQUEST -> {
// If request is cancelled, the result arrays are empty.
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
//granted - you are not able to use Location Functionality
} else {
// permission denied
Toast.makeText(this, "Location Functionality Disabled.", Toast.LENGTH_LONG).show()
}
return
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
}
}
}
You can also request multiple permissions at once.
Android 6.0 multiple permissions

Related

Android application permission settings

My internal android application worked fine on Samsung Tab S2 and it automatically got permissions to access 'storage' and 'location' of the device. But, when I am installing the application on newer Samsung Galaxy Tab S7, I have to manually provide permission for the app in settings. By default it is set to "No permissions allowed" How cam I automate this.
AndroidManifest.xml has following settings
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="22"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Android permissions went through a radical change after android M was released. before that, developers can simply jam all the permissions in the AndroidManifesto file, and before the user installs the app, he/she has to approve all the permissions to run the app.
However, things are different now. Android expects that these permissions will be granted at rather runtime, i.e. when a feature that needs that permission is executed, it first requests for that permission, and based on user's reply handle that. If permission is granted, then good. If not, then simply display a message maybe stating that this feature will not work in the absence of that permission. In which case, because the user has already declined the permission, he/she now has to go to the settings to enable the previously declined permission.
You have to grant permission from the user. You can use it inside Fragment:
Java:
if (ActivityCompat.checkSelfPermission(getContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(getActivity(),
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION);
} else {
Log.e("DB", "PERMISSION GRANTED");
}
Kotlin:
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(getActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION)
} else {
Log.e("DB", "PERMISSION GRANTED")
}
and inside Activity:
Java:
int checkPermission= ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA);
if (checkPermission!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity)getContext(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
}
else {
Log.e("DB", "PERMISSION GRANTED")
}
Kotlin:
val checkPermission = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA)
if (checkPermission != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(getContext() as Activity, arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION)
}
else
{
Log.e("DB", "PERMISSION GRANTED")
}

Android's WRITE_EXTERNAL_STORAGE permission issue on Samsung Galaxy Api 23 version 6

I need to open a pdf using a uri.
I have the code in place to open the pdf.
My code works fine on Api greater than 23.
I get the following SecurityException when I try to download the file on a Samsung Galaxy device with Api 23 and version 6.
Here is the exception:
01-25 19:28:38.723 6655-6667/android.process.media E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: No permission to write to /storage/emulated/0/Download/Canto Quick Start Guide.pdf: Neither user 10022 nor current process has android.permission.WRITE_EXTERNAL_STORAGE.
at android.app.ContextImpl.enforce(ContextImpl.java:1438)
at android.app.ContextImpl.enforceCallingOrSelfPermission(ContextImpl.java:1470)
at android.content.ContextWrapper.enforceCallingOrSelfPermission(ContextWrapper.java:675)
at com.android.providers.downloads.DownloadProvider.checkFileUriDestination(DownloadProvider.java:724)
at com.android.providers.downloads.DownloadProvider.insert(DownloadProvider.java:558)
at android.content.ContentProvider$Transport.insert(ContentProvider.java:263)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:163)
at android.os.Binder.execTransact(Binder.java:507)
I have setup the required permission in manifest file
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<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" />
I have the following check in place to test if the user does not have WRITE_EXTERNAL_STORAGE permission then ask the user for granting access.
int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 2;
// Check whether this app has write external storage permission or not.
int writeExternalStoragePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
// If do not grant write external storage permission.
if (writeExternalStoragePermission != PackageManager.PERMISSION_GRANTED) {
// Request user to grant write external storage permission.
((MainActivity)activity).getSharedPreferenceManager().add(PreferenceConstants.SHAREPOINT_FILE_URI, getUrl((SharepointFile) object, activity));
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PermissionConstants.PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getUrl((SharepointFile) object, activity)));
intent.setDataAndType(Uri.parse(getUrl((SharepointFile) object, activity)), "application/pdf");
activity.startActivity(intent);
}
I override the onRequestPermissionResult in MainActivity.java so that as soon as the user grants permission then the download can be initiated.
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PermissionConstants.PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
String fileUri = getSharedPreferenceManager().get(PreferenceConstants.SHAREPOINT_FILE_URI);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fileUri));
startActivity(intent);
} else {
getSharedPreferenceManager().remove(PreferenceConstants.SHAREPOINT_FILE_URI);
}
break;
}
}
I have the code to ask the user for permission. I do get the dialog/alert to allow access. Once the user clicks allow, I see that it still gives the above exception. I went in settings to check my app's permission and see that it is turned "on" for storage. Why would I still get permission issue? Any pointers on what I could be missing here? Appreciate your help!
It is just an assumption but i see you have declared both
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
But docs says:
Any app that declares the WRITE_EXTERNAL_STORAGE permission is implicitly granted this (READ_EXTERNAL_STORAGE) permission.
Try to remove
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Android: WRITE_EXTERNAL_STORAGE permission not accepted by device

I'm having a rather strange problem with an Android app I'm writing.
In my app, I use an intent to tell the phone's camera app to take a picture for me. After I take this picture, I want to register the newly taken photo with the device's MediaStore content provider in order to make it show up in the regular "gallery" app.
To do this, I know I need the WRITE_EXTERNAL_STORAGE permission, but even when it's in my manifest I get a permission denied exception. What do I have to do to get this permission? I'm running Android 6.0.1.
Here's my permissions XML in the manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here's the code that causes the exception:
// insert photo into phone's main photo content provider
ContentResolver cr = getActivity().getContentResolver();
try {
MediaStore.Images.Media.insertImage(cr, photoFile.getPath(),
"Image Capture", "Custom Image capture");
} catch (FileNotFoundException foe) {
Log.e(DEBUG, foe.getMessage());
}
And here's the exception I get:
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=2436, uid=10041 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
EDIT: I should probably mention:
Right now my app uses getExternalFilesDir(Environment.DIRECTORY_PICTURES), which returns the path /sdcard/Android/data/<package>/files/Pictures to save it's photos. I want them to go where the camera app normally puts them, in /sdcard/DCIM/Camera.
You should add the android:maxSdkVersion="18" to the WRITE_EXTERNAL_STORAGE as well. Your code should look like this:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
This may be a problem with respect to you requesting the permission but not being granted the permission by the user. Have a look at my answer # https://stackoverflow.com/a/35574084/529691
And see if that helps.
You should promt the user to provide you permission:
int externalPermissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (externalPermissionCheck==-1){
askPermissionStorage();
}
private void askPermissionStorage() {
//for media
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.
WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//insert explanation
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//if you want to explaian to the user
} else {//if no explanation needed
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
}
The above is for save the picture\video
and this is for the camera permission:
int cameraPermissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA);
if (cameraPermissionCheck == -1) {
askPermissionCamera();
}
private void askPermissionCamera() {
//for camera
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.
CAMERA) != PackageManager.PERMISSION_GRANTED) {
//insert explanation
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
//if you want to explaian to the user
} else {//if no explanation needed
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CAMERA);
}
}
}

I am setting permissions in manifest but have to enable manually in `marshmallow`

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();
}
}
}

Neither user 10102 nor current process has android.permission.READ_PHONE_STATE

I am trying to call getCallCapablePhoneAccounts() method of android.telecom.TelecomManager class. Though i have added required user-permission, i am getting Security exception.
Here is the line of code where i am getting exception
List<PhoneAccountHandle> list = getTelecomManager().getCallCapablePhoneAccounts();
user permission added in manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Exception stacktrace
Caused by: java.lang.SecurityException: getDefaultOutgoingPhoneAccount: Neither user 10102 nor current process
has android.permission.READ_PHONE_STATE.
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at com.android.internal.telecom.ITelecomService$Stub$Proxy.getDefaultOutgoingPhoneAccount(ITelecomService.java:615)
at android.telecom.TelecomManager.getDefaultOutgoingPhoneAccount(TelecomManager.java:439)
On Android >=6.0, We have to request permission runtime.
Step1: add in AndroidManifest.xml file
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Step2: Request permission.
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_READ_PHONE_STATE);
} else {
//TODO
}
Step3: Handle callback when you request permission.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_READ_PHONE_STATE:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
//TODO
}
break;
default:
break;
}
}
Edit:
Read official guide here Requesting Permissions at Run Time
Are you running Android M? If so, this is because it's not enough to declare permissions in the manifest. For some permissions, you have to explicitly ask user in the runtime: http://developer.android.com/training/permissions/requesting.html
I was experiencing this problem on Samsung devices (fine on others). like zyamys suggested in his/her comment, I added the manifest.permission line but in addition to rather than instead of the original line, so:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.Manifest.permission.READ_PHONE_STATE" />
I'm targeting API 22, so don't need to explicitly ask for permissions.

Categories

Resources