Разрешения на хранилище Android 11 с ограниченной областью действия
Я пытаюсь лучше понять, что я смогу делать, когда выйдет версия Android 11.
Мое приложение использует пути к файлам изображений, предоставленные Environment.getExternalStorageDirectory()
для создания альбомов фотографий, но с Android 11 у меня не будет прямого доступа к файлам.
Согласно документации разработчиков Android, они недавно представили MANAGE_EXTERNAL_STORAGE
разрешение, но я не понял, добавив это разрешение, я смогу продолжить доступ к файлу, Environment
или не.
Есть у кого-нибудь идея???
Благодарность
18 ответов
Согласно документации разработчиков Android, они недавно представили разрешение MANAGE_EXTERNAL_STORAGE, но я не понял, добавив это разрешение, я смогу продолжить доступ к файлу через Environment или нет.
Да, вы будете. Однако имейте в виду, что если вы собираетесь распространять свое приложение в Play Store (и, возможно, в другом месте), вам нужно будет обосновать причину запроса этого разрешения. Так что, если у вас есть очень веские причины для использованияMANAGE_EXTERNAL_STORAGE
, пожалуйста, используйте что-нибудь другое.
Android 11
If you targeting Android 11 (
targetSdkVersion 30
) then you required following permissions declare in AndroidManifest.xml for modifying and document access.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
For Android 10 you place following line in your AndroidManifest.xml tag
android:requestLegacyExternalStorage="true"
below code to check permission is allowed or denied
private boolean checkPermission() {
if (SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
} else {
int result = ContextCompat.checkSelfPermission(PermissionActivity.this, READ_EXTERNAL_STORAGE);
int result1 = ContextCompat.checkSelfPermission(PermissionActivity.this, WRITE_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
}
}
below code for requesting permission in android 11 or below
private void requestPermission() {
if (SDK_INT >= Build.VERSION_CODES.R) {
try {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse(String.format("package:%s", new Object[]{getApplicationContext().getPackageName()})));
startActivityForResult(intent, 2296);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivityForResult(intent, 2296);
}
} else {
//below android 11
ActivityCompat.requestPermissions(PermissionActivity.this, new String[]{WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
Handling permission callback for Android 11 or above version
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2296) {
if (SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
// perform action when allow permission success
} else {
Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
}
}
}
}
Handling permission callback for below Android 11
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0) {
boolean READ_EXTERNAL_STORAGE = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean WRITE_EXTERNAL_STORAGE = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (READ_EXTERNAL_STORAGE && WRITE_EXTERNAL_STORAGE) {
// perform action when allow permission success
} else {
Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
}
}
break;
}
}
Android 11 не позволяет получить прямой доступ к файлам из хранилища, вам необходимо выбрать файл из хранилища и скопировать его в пакет приложения chache com.android.myapp. Ниже приведен метод копирования хранилища файловой формы в кеш пакетов приложения.
private String copyFileToInternalStorage(Uri uri, String newDirName) {
Uri returnUri = uri;
Cursor returnCursor = mContext.getContentResolver().query(returnUri, new String[]{
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
}, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
String name = (returnCursor.getString(nameIndex));
String size = (Long.toString(returnCursor.getLong(sizeIndex)));
File output;
if (!newDirName.equals("")) {
File dir = new File(mContext.getFilesDir() + "/" + newDirName);
if (!dir.exists()) {
dir.mkdir();
}
output = new File(mContext.getFilesDir() + "/" + newDirName + "/" + name);
} else {
output = new File(mContext.getFilesDir() + "/" + name);
}
try {
InputStream inputStream = mContext.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(output);
int read = 0;
int bufferSize = 1024;
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
inputStream.close();
outputStream.close();
} catch (Exception e) {
Log.e("Exception", e.getMessage());
}
return output.getPath();
}
Когда вы обновляете свое устройство Android с api 10(29) до android 11 (30) Api, он не работает для извлечения данных из хранилища вашего устройства или мобильного каталога, который я проверил сегодня в магазине воспроизведения тысячи приложений, которые загружаются миллионами в реальном времени в игре store, они не работают на android 11, потому что android 11 представил новое обновление хранилищ с ограниченным объемом, где вам нужно реализовать новые методы для получения медиафайла с помощью объекта MediaStore,
до этого на android 10 мы использовали
android:requestLegacyExternalStorage="true"
tools:targetApi="q"
в mainfest в атрибуте application теперь этот метод не работает в android 11.
так что переходите на новые обновления сейчас, спасибо
Я нашел такой способ для Android 11 (SDK R - 30):
1- В манифесте необходимо добавить это разрешение: (только для R)
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
2- Запросите диалог ОС, чтобы запросить разрешение:
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE}, 1);
3- Убедитесь, что ваше приложение может получить доступ к хранилищу :
if (!Environment.isExternalStorageManager())
4- Используйте намерение, чтобы открыть «Доступ ко всем файлам» для вашего приложения.
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
Примечание: этот ответ не требует разрешения
В android 10 и выше
MANAGE_EXTERNAL_STORAGE
мы не можем использовать его для приложений игрового магазина, если только файловый менеджер или антивирус не делают его бесполезным.
поэтому для доступа к фотографиям из хранилища без MANAGE_EXTERNAL_STORAGE ниже ответ был бы полезен
В манифесте
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
для доступа к медиафайлам
// Need the READ_EXTERNAL_STORAGE permission if accessing video files that your
// app didn't create.
// Container for information about each video.
data class Image(val uri: Uri,
val name: String,
val duration: Int,
val size: Int
)
val imgList = mutableListOf<Image>()
val collection =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(
MediaStore.VOLUME_EXTERNAL
)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val projection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE
)
// Display videos in alphabetical order based on their display name.
val sortOrder = "${MediaStore.Images.Media.DISPLAY_NAME} ASC"
val query = ContentResolver.query(
collection,
projection,
null,
null,
sortOrder
)
query?.use { cursor ->
// Cache column indices.
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
val nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)
val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE)
while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val size = cursor.getInt(sizeColumn)
val contentUri: Uri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
id
)
// Stores column values and the contentUri in a local object
// that represents the media file.
imgList += Image(contentUri, name, size)
}
}
создать файл
// Request code
const val CREATE_FILE = 1
private fun createFile(pickerInitialUri: Uri) {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "Type of file"
putExtra(Intent.EXTRA_TITLE, "Name of File")
// Optionally, specify a URI for the directory that should be opened in
// the system file picker before your app creates the document.
putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
}
startActivityForResult(intent, CREATE_FILE)
}
строгое разрешение и должно использоваться только в допустимых целях, например, файловый менеджер и антивирусные приложения. Смотрите использование .
Я бы предложил с этой библиотекой что-нибудь попроще . Вы можете получить доступ к хранилищу с заданной областью без разрешения на полный диск (
MANAGE_EXTERNAL_STORAGE
). Этот код попросит пользователя предоставить доступ:
class MainActivity : AppCompatActivity() {
private val storageHelper = SimpleStorageHelper(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupSimpleStorage(savedInstanceState)
setupButtonActions()
}
private fun setupButtonActions() {
btnRequestStorageAccess.setOnClickListener {
storageHelper.requestStorageAccess()
}
btnSelectFolder.setOnClickListener {
storageHelper.openFolderPicker()
}
btnSelectFile.setOnClickListener {
storageHelper.openFilePicker()
}
}
private fun setupSimpleStorage(savedInstanceState: Bundle?) {
savedInstanceState?.let { storageHelper.onRestoreInstanceState(it) }
storageHelper.onStorageAccessGranted = { requestCode, root ->
Toast.makeText(this, "Yay, granted!", Toast.LENGTH_SHORT).show()
}
storageHelper.onFileSelected = { requestCode, file ->
Toast.makeText(this, file.fullName, Toast.LENGTH_SHORT).show()
}
storageHelper.onFolderSelected = { requestCode, folder ->
Toast.makeText(this, folder.getAbsolutePath(this), Toast.LENGTH_SHORT).show()
}
}
}
Поскольку прямые пути к файлам (
java.io.File
) больше не надежны, поэтому вам нужно
DocumentFile
который управляет файлами через URI. Библиотека также предоставляет богатые функции расширения, например:
-
DocumentFile.getProperties()
-
DocumentFile.search()
-
DocumentFile.deleteRecursively()
-
DocumentFile.openOutputStream()
-
DocumentFile.copyFileTo()
-
List<DocumentFile>.moveTo()
, так далее.
В Android 11 это мой полностью работающий код для запуска и запуска камеры:
`
<!--Still need to request legacy storage for devices running on API 29 and below otherwise they won't work -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourpackage">
<!-- For Various Types -->
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="vnd.android.cursor.dir/email" />
</intent>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
<intent>
<action android:name="android.intent.action.CALL" />
</intent>
</queries>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- ... Rest of manifest -->
<application
...
android:requestLegacyExternalStorage="true"
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
</application>
</manifest
`
Документ file_path.xml находится в папке res / xml и содержит следующее для изображений:
`
<external-files-path
name="internal_images"
path="files/Pictures" />
<external-files-path
name="internal_images_alternate"
path="Pictures" />
</paths>
`
Затем, когда я действительно проверял параметры хранения, я реализовал следующий фрагмент кода:
`
private boolean hasManageExternalStoragePermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
return true;
} else {
if (Environment.isExternalStorageLegacy()) {
return true;
}
try {
Intent intent = new Intent();
intent.setAction(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:com.example.yourpackage"));
startActivityForResult(intent, RESULT_CODE); //result code is just an int
return false;
} catch (Exception e) {
return false;
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (Environment.isExternalStorageLegacy()) {
return true;
} else {
try {
Intent intent = new Intent();
intent.setAction(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:com.example.yourpackage"));
startActivityForResult(intent, RESULT_CODE); //result code is just an int
return false;
} catch (Exception e) {
return true; //if anything needs adjusting it would be this
}
}
}
return true; // assumed storage permissions granted
}
`
Далее для запроса разрешения: `
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); //permission request code is just an int
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); //permisison request code is just an int
}
`
Тогда (и я знаю, что это выходит за рамки исходного вопроса) у вас есть перспектива использования намерения камеры, которое сейчас выглядит следующим образом:
`
public static Intent getCameraIntentWithUpdatedPackages(Context context){
List<ResolveInfo> resolveInfo = new ArrayList<>();
final Intent capturePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
PackageManager pm = context.getPackageManager();
resolveInfo = pm.queryIntentActivities(capturePhoto, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
// For Android 11 we need to add specific camera apps
// due them are not added during ACTION_IMAGE_CAPTURE scanning...
resolveInfo.addAll(getCameraSpecificAppsInfo(context));
}
return capturePhoto;
}
private static List<ResolveInfo> getCameraSpecificAppsInfo(Context context){
List<ResolveInfo> resolveInfo = new ArrayList<>();
if (context == null){
return resolveInfo;
}
PackageManager pm = context.getPackageManager();
for (String packageName : CAMERA_SPECIFIC_APPS) {
resolveInfo.addAll(getCameraSpecificAppInfo(packageName, pm));
}
return resolveInfo;
}
private static List<ResolveInfo> getCameraSpecificAppInfo(String packageName, PackageManager pm){
Intent specificCameraApp = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
specificCameraApp.setPackage(packageName);
return pm.queryIntentActivities(specificCameraApp, 0);
}
public static File dispatchTakePictureIntent(Context context, String photoNameSuffix) {
Intent takePictureIntent = getCameraIntentWithUpdatedPackages(context);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile(activity, photoNameSuffix);
} catch (IOException ex) {
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = Uri.fromFile(photoFile);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
} else {
File file = new File(photoURI.getPath());
if (!file.exists()) {
file.mkdirs();
file.mkdir();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
Uri photoUri = FileProvider.getUriForFile(context.getApplicationContext(), context.getApplicationContext().getPackageName() + ".provider", file);
activity.grantUriPermission(photoURI.getAuthority(), photoUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
}
//disable strict mode policies
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
context.startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
return photoFile;
}
return null;
}
static final String[] CAMERA_SPECIFIC_APPS = new String[]{
"best.camera",
"net.sourceforge.opencamera",
"com.google.android.GoogleCamera",
"tools.photo.hd.camera",
};
`
И точно так же у нас есть изображение, которое мы можем переименовать в наш собственный каталог, предполагая, что имя пакета предоставлено всем файлам!
Если вы хотите писать и читать файлы с устройства. Вы можете в основном использовать
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
(это не обязательно ДОКУМЕНТЫ КАТАЛОГА) вместо
Environment.getExternalStorageDirectory()
, тебе не нужно просить
MANAGE_EXTERNAL_STORAGE
разрешение. Таким образом, он нормально работает на Android 11.
Я решил проблему -
Делать -
- Сохраните во внешнем каталоге, так как это поможет читать в SDK версии 30 или выше.
- Добавьте '//' + путь к каталогу, и ваша проблема будет решена. Это означает, что ваш путь будет '//' + getExternalStorageDirectory ()) !. path
- Добавить разрешение на чтение и запись - в манифесте
для доступа к медиафайлам
Не используйте это, так как ваше приложение не будет принято в магазине игр.
-
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
Это код для сохранения и извлечения файла, и он работает как с SDK> 30, так и с SDK = <30.
final directory = (await getExternalStorageDirectory())!.path;
ByteData? byteData =
await (image.toByteData(format: ui.ImageByteFormat.png));
Uint8List pngBytes = byteData!.buffer.asUint8List();
File imgFile = new File('$directory/screenshot${rng.nextInt(2000)}.png');
await imgFile.writeAsBytes(pngBytes);
setState(() {
_imageFile = imgFile;
});
// Add '//' + directory path & your problem will be resolved
return '//'+imgFile.path;
Теперь поделитесь файлом - takeScreenshot(). Then((value) => Share.shareFiles(['$value'],text:'Hello'),);
private fun loadFilesFromSharedStorage() {
try {
val projection = arrayOf(
MediaStore.MediaColumns._ID,
MediaStore.MediaColumns.DISPLAY_NAME
)
val selection = when (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
true -> "${MediaStore.MediaColumns.RELATIVE_PATH} LIKE ?"
else -> MediaStore.Images.Media.DATA + " like ? "
}
val selectionArgs = arrayOf("%test%")
val uriExternal = MediaStore.Files.getContentUri("external")
contentResolver.query(
uriExternal,
projection,
selection,
selectionArgs,
null
)?.use {
val idColumn = it.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)
while (it.moveToNext()) {
try {
val contentUri: Uri = ContentUris.withAppendedId(
uriExternal,
it.getLong(idColumn)
) /*Use this URI for next*/
} catch (e: Exception) {
e.printStackTrace()
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Используйте блок для извлечения файлов из общего хранилища в Android11 и используйте его
В расположении файла (где бы вы его ни использовали) используйте
mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
вместо того
Environment.getExternalStorageDirectory();
И в использовании разрешений (см. Комментарий вне разрешения)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// return Environment.isExternalStorageManager();
return true;
}
Я тоже несколько часов искал решение и тестировал некоторые подходы. В моем приложении пользователи могут отправлять электронные письма с PDF-документом в качестве вложения, и внезапно, начиная с Android 11, вложение оказалось пустым из-за изменений разрешений в Android. Для получения файла я использую FileProvider. Предлагаемые методы, которые я нашел здесь, но также и в других потоках, не работали, пока я не протестировал свои собственные и случайно не сделал то же самое, что и Monu meena, и не добавил это в свой файл манифеста Android:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
Это единственное рабочее решение в моем случае. Я не удалял разрешения на чтение или запись, а также не устанавливал целевой sdk на 29 или ниже, мой целевой sdk по-прежнему 30, и он также работает для устройств с API ниже, чем 30. Я успешно протестировал несколько устройств с разными версиями API в эмуляторе студии Android.
Так что попробуйте, иногда самые простые решения оказываются лучшими.
Включить MANAGE_EXTERNAL_STORAGE
набор приложений оболочки adb --uid PACKAGE_NAME MANAGE_EXTERNAL_STORAGE разрешить
В Android 11 вы не можете напрямую получать доступ к файлам и папкам, кроме папки приложения, и, следовательно, вы должны запрашивать разрешение каждый раз, когда получаете доступ к новому файлу. Однако это не требуется для СМИ. https://www.youtube.com/watch?v=K56XkyICd2I Вот видео, которое фактически демонстрирует весь процесс доступа к хранилищу и получения разрешений.
В моем случае просто нужно было создать файл .csv, а затем отправить на сервер, я должен был следовать этому документу.
File folder = new File(getBaseContext().getFilesDir(), "/test/CSV");
filepath = folder.toString() + "/" + id + ".csv";
Доступ к немедиафайлам на Android 11+
В Android 11+ немедийные файлы (например, txt, pdf, csv,...) доступны тогда и только тогда, когда
текстовые файлы находятся в папке → ASD или → Private (т.е. были сохранены там), или текстовые файлы находятся в одной из общих папок /Documents или /Download, и эти файлы были созданы самим приложением, или SAF используется или запрашивается и предоставляется разрешение MANAGE_EXTERNAL_STORAGE*. *` На самом деле это не вариант, поскольку приложение, запрашивающее это разрешение, (скорее всего) не будет разрешено в Google Play Store.
Примечание. Разумеется, все файлы в ресурсах можно прочитать. Однако они доступны только для чтения.
Доступ к медиафайлам на Android 11+
Без разрешения READ медиафайлы (например, jpg, png, mp3, mp4,...) можно читать на Android 11+ тогда и только тогда, когда
эти файлы расположены в одной из общих папок (/Pictures, /DCIM, /Documents, /Download, /Music, /Movies) и были созданы самим приложением, либо они находятся в ASD, либо в личном каталоге. . С разрешением READ все медиафайлы можно читать из всех областей внешнего хранилища (также из корневого каталога).
Без разрешения WRITE медиафайлы можно сохранять на Android 11+ тогда и только тогда, когда
они хранятся в ASD, в личном каталоге или в одной из общих папок. Приватный каталог находится во внутренней памяти:
/data/user/0//files/ Примечание. Поскольку разрешение WRITE_EXTERNAL_STORAGE больше не существует в Android 11+, без MANAGE_EXTERNAL_STORAGE невозможно сохранять файлы за пределами папок ASD, Private dir или Shared. Или вы должны использовать SAF.
Ins простой способ, только нам нужно включить разрешение ниже
$
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
тогда мы можем использовать наши старые коды для выполнения любых действий