Reputation: 1090
From Android Docs, https://developer.android.com/training/data-storage/manage-all-files#all-files-access
"An app can request All files access from the user by doing the following:
Declare the MANAGE_EXTERNAL_STORAGE permission in the manifest.
Use the ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page where they can enable the following option for your app: Allow access to manage all files."
The only way I know how to request permissions is with ActivityCompat
. I've tried:
ActivityCompat.requestPermissions(this, new String[]{Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION},1);
and
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.MANAGE_EXTERNAL_STORAGE},1);
Neither of which do anything.
The Android docs are extensive but not exactly the most welcoming for newcomers. I understand intents, and know they can be used to switch between activities, but I don't know what an "intent action" is and how it can be used to request permissions
Upvotes: 32
Views: 66479
Reputation: 1006539
In Kotlin:
val uri = Uri.parse("package:${BuildConfig.APPLICATION_ID}")
startActivity(
Intent(
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
uri
)
)
(from this sample project)
You are probably used to an implicit Intent
. The docs are asking you to use an explicit Intent
, one with an action string and, in this case, a Uri
. The Uri
will have the package
scheme and identify your app by its application ID.
That code snippet will start a system-supplied activity that, in theory, will let the user opt into granting your app the MANAGE_EXTERNAL_STORAGE
permission.
This API is available for Android R and higher. It will throw ActivityNotFoundException
for Android Q and below.
Upvotes: 33
Reputation: 11
Intent Environment = new
Intent().setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
.setData(Uri.parse("package:" + getPackageName()));
if (Environment.resolveActivity(getPackageManager())!=null) {
startActivity(Environment);
}
Upvotes: 1
Reputation: 890
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
try {
var intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
Uri.parse("package:" + packageName))
startActivityForResult(intent, REQUEST_PERMISSION)
} catch (e: Exception) {
Logger.d(TAG, e.message)
var intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
startActivityForResult(intent, REQUEST_PERMISSION)
}
}
}
Note: ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
and ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
are different.
Both of them can direct user to system settings page.
The difference is:
ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
, with this action, direct user to the package ("package:<package-name>
") setting page.
ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
, this action direct user to app list. All apps which want to manage all files will show in that list.
Upvotes: 4
Reputation: 1995
You can create an intent like this :
Intent intent = new Intent(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + BuildConfig.APPLICATION_ID));
Now, you can launch this intent with startActivityForResult.
final static int APP_STORAGE_ACCESS_REQUEST_CODE = 501; // Any value
startActivityForResult(intent, APP_STORAGE_ACCESS_REQUEST_CODE);
In your onActivityResult method, you can check whether the user granted you the permission or not.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == APP_STORAGE_ACCESS_REQUEST_CODE && Environment.isExternalStorageManager())
// Permission granted. Now resume your workflow.
}
}
You can also do this with the new ActivityResultAPI by launching the activity with :
// Initialize the variable in before activity creation is complete.
val storagePermissionResultLauncher = registerForActivityResult(StartActivityForResult(),
ActivityResultCallback<ActivityResult?> {
if (Environment.isExternalStorageManager())
{
// Permission granted. Now resume your workflow.
}
})
// launch the above intent.
storagePermissionResultLauncher.launch(intent)
Also, make sure that you add this permission entry in your AndroidManifest.xml.
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
Upvotes: 27
Reputation: 201
If Uri will be used in Intent, Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION can be used instead of Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION.
if(SDK_INT >= 30){
if(!Environment.isExternalStorageManager()){
Snackbar.make(findViewById(android.R.id.content), "Permission needed!", Snackbar.LENGTH_INDEFINITE)
.setAction("Settings", new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri);
startActivity(intent);
} catch (Exception ex){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
}
})
.show();
}
}
Upvotes: 19
Reputation: 581
1 Did you add uses-permission in the AndroidManifest.xml? like :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2 You can refer this github library:
https://github.com/getActivity/XXPermissions
It wraped the api of google sdk, and provide a simple way to apply the permissions.
Upvotes: 1