I am working on a files app and after targeting to API-30, I need permissions for not just media store permission (WRITE_EXTERNAL_STORAGE), but also need to be an external storage manager (MANAGE_EXTERNAL_STORAGE). In order to do so, I have to show 2 different system dialogs to the customer. The first one is the media store permissions dialog:
/* Code to show this permission */
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_EXTERNAL_STORAGE},
1);
And then I have to show the following one to get external storage manager permissions:
/* Code to show this permission */
final Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
final Uri uri = Uri.fromParts("package", activity.getApplicationContext().getPackageName(), null);
intent.setData(uri);
activity.startActivity(intent);
Is there something in the android system that shows user a dialog that bundles all the storage permissions together, or any android system flow that can be launched that guides user throughout both permission together? Having two different flows seems like a terrible amount of redundant logic that needs to be owned by apps. I was not able to find something like that, so asking here if I missed anything.
Is there something in the android system that shows user a dialog that bundles all the storage permissions together
Not in terms of MANAGE_EXTERNAL_STORAGE, as that is not a runtime permission that you handle via requestPermissions(). READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE can be requested together using requestPermissions().
or any android system flow that can be launched that guides user throughout both permission together?
No, sorry.
Note that I have not tried holding MANAGE_EXTERNAL_STORAGE without WRITE_EXTERNAL_STORAGE. Perhaps WRITE_EXTERNAL_STORAGE is not needed if you hold MANAGE_EXTERNAL_STORAGE. The documentation suggests that this might be the case.
Having two different flows seems like a terrible amount of redundant logic that needs to be owned by apps
Very few apps should be asking the user to grant MANAGE_EXTERNAL_STORAGE. And apparently Google really wants users to think through whether they should be granting that permission to your app.
Related
I want to read contact like this
Should I ask permission for this?
val intent = Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI)
startActivityForResult(intent, RESULT_PICK_CONTACT)
Android platform is moving towards creating a more user-safe experience. There are new safety features coming out that gives the user an option to only enable certain features for the session that the user is during the app's usage. It makes sense to be explicit about these permissions with the end user so they feel more clear about how they will expose themselves.
I'm testing my app on an emulator. I have an export function where I create and write to a file in the external storage's downloads directory. And I also have an import function where I read a file from the external storage's downloads directory.
From Android documentation:
If the device is running Android 5.1 or lower, or your app's target SDK is 22 or lower: If you list a dangerous permission in your manifest, the user has to grant the permission when they install the app; if they do not grant the permission, the system does not install the app at all.
If the device is running Android 6.0 or higher, and your app's target SDK is 23 or higher: The app has to list the permissions in the manifest, and it must request each dangerous permission it needs while the app is running. The user can grant or deny each permission, and the app can continue to run with limited capabilities even if the user denies a permission request.
My emulator is running on Android 6.0 and my app's target SDK is 25, therefore I must also request each dangerous permission it needs while the app is running. I did so for the export functionality and everything works properly. However, when I'm implementing the import function I didn't request a permission during runtime. And the strange thing is I'm still able to read from my external storage's permission without READ_EXTERNAL_STORAGE being requested and granted at runtime. READ_EXTERNAL_STORAGE is a dangerous permission according to this Android documentation .
To verify, I made sure to disable permissions before I started using the feature and after it is completed, I verified again that the permission still wasn't granted. Although I'm happy with the behaviour since it's working without me requesting permission at runtime, but according to the documentations I don't believe this behaviour is expected. That's why I will like to know what's causing this and to figure out the problem before I publish any changes for the app.
Here's a code snippet of 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" />
The code snippet where I pick a file to read:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("text/*");
startActivityForResult(intent, GET_FILE_RESULT_CODE);
The code snippet where I read the file chosen from the code snippet above (exportFile is simply the URI from onActivityResult):
BufferedReader br;
try {
br = new BufferedReader(new InputStreamReader(context.getContentResolver().openInputStream(exportFile)));
String line;
// Skip first header line
br.readLine();
while ((line = br.readLine()) != null) {...}
Thanks!
There's a well explanation here,
READ_EXTERNAL_STORAGE
Provides protected read access to external storage. In Android 4.1 by
default all applications still have read access. This will be changed
in a future release to require that applications explicitly request
read access using this permission. If your application already
requests write access, it will automatically get read access as well.
There is a new developer option to turn on read access restriction,
for developers to test their applications against how Android will
behave in the future.
In short, READ_EXTERNAL_STORAGE only exists as of Jelly Bean (Level 16). So, unless you're using a Jelly Bean phone and set the developer option "Protect USB storage" it won't be a problem.
You know,Android Runtime Permissions are grouped, since you applied for WRITE_EXTERNAL_STORAGE permission in the manifest already, so there's no need to apply for READ_EXTERNAL_STORAGE permissions.Both of them are the same group.
This confuses me a lot when I test my app on android 6.0+ devices.Since in android 6.0+,we should ask the user to accept some dangerous permissions.I pressed refuse button when it ask me for
WRITE_EXTERNAL_STORAGE
permission and then,if my file cache path was data/data/com.myapp(getApplicationInfo().dataDir),it can still be cached. And for any other path e.g. Environment.getExternalStorageDirectory().getAbsolutePath(),it won't be cached.
So why does this happen?
Is there a way to choose which order the user is prompted for permissions in Android Marshmellow's new permissions dialog?
When the user launches the camera in my app, I'm prompting for:
Manifest.permission.CAMERA
Manifest.permission.WRITE_EXTERNAL_STORAGE
Manifest.permission.RECORD_AUDIO
Because it makes the most sense (e.g. open camera, app requests camera permissions), I want the permissions to be requested in that order as well. But they aren't requested in that way - the Permissions dialog seems to just ignore the order I have in the String array.
Code below, using the EasyPermissions library, but the same thing happens without the EasyPermissions library.
ArrayList<String> permissionsToRequest = new ArrayList<String>();
permissionsToRequest.add(Manifest.permission.CAMERA);
permissionsToRequest.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
permissionsToRequest.add(Manifest.permission.RECORD_AUDIO);
EasyPermissions.requestPermissions(
this,
"To take pictures & record video, we need access to your device's camera & storage. Allow?",
R.string.acceptPermission, R.string.declinePermission,
RequestConstants.REQUEST_CAMERA_PERMISSIONS,
permissionsToRequest.toArray(new String[0])
);
Regardless of how I order the permissions in permissionsToRequest, the user is prompted in the same order (Audio, Storage, Camera), which in my opinion is the least intuitive order. Any way to fix this?
Although there isn't a clear way to define the order of permission, I found that it is somehow related to the order defined in the AndroidManifest.xml and in the array passed in Activity.requestPermissions(String[] permissions, String requestCode)
In a device, the order of the permission array was the order it showed in the screen. In a different device, the order defined in the manifest prevailed.
Hope this helps.
I've a problem with content provider and custom permissions.
Let's suppose that App A have a content provider containing wonderful informations. These informations are a little bit intrusive, that's why it's better to have a permission to read them.
Let's suppose that App B is a 3rd party application and want to access to the content provider of A.
Let's suppose that the permission to read into the content provider is "com.custom.a.readpermission".
In A manifest, there is :
<permission android:name="com.custom.a.readpermission"/>
<provider android:name="com.a.provider.MyProvider"
android:exported="true"
android:authorities="com.a.provider.MyProvider"
android:readPermission="com.custom.a.readpermission"/>
In B manifest, there is :
<uses-permission android:name="com.custom.a.readpermission"/>
So, now, if I install A; after, I install B. B can access to the data.
But, if I install B before A, I get :
java.lang.SecurityException: Permission Denial: opening provider com.a.provider.MyProvider requires com.custom.a.readpermission
So, how to manage a custom permission in that case ?
So, how to manage a custom permission in that case ?
Your primary options are:
Use a built-in system permission, as opposed to a custom one. This is a good idea in general, if the nature of the sensitive data is similar to other data already defended by built-in permissions.
Catch this exception and tell the user that they need to uninstall A and B and install them in the proper order.
If A and B are both by the same author, use a protectionLevel signature permission and have the same <permission> element in both A and B. Then the installation order will not matter, and the user won't be bothered with any prompts to agree to this permission.
However, bear in mind that prior to Android 5.0, the fact that option #3 works means that any app installed before A could do the same thing as B does, except downgrading the protectionLevel from signature to normal. This is a known vulnerability. Android 5.0 requires that custom permissions are defined on a "first one in wins" basis, and the second and subsequent apps trying to define the same <permission> have to be signed by the same signing key as the app that actually did define it.
In truth, permissions are great for pre-installed apps and the OS itself, but defining custom permissions at the app level is... less than great.