Разрешения на хранилище 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.

Я решил проблему -

Делать -

  1. Сохраните во внешнем каталоге, так как это поможет читать в SDK версии 30 или выше.
  2. Добавьте '//' + путь к каталогу, и ваша проблема будет решена. Это означает, что ваш путь будет '//' + getExternalStorageDirectory ()) !. path
  3. Добавить разрешение на чтение и запись - в манифесте

для доступа к медиафайлам

Не используйте это, так как ваше приложение не будет принято в магазине игр.

  1. <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" />

тогда мы можем использовать наши старые коды для выполнения любых действий

Другие вопросы по тегам