Переименование (перемещение) изображений из DCIM/Camera в другую директорию (созданную другим приложением) на Android.

Вопрос или проблема

Я пытаюсь создать приложение для сортировки своих ранее сделанных фотографий на внешнем хранилище.
Я хочу переместить их в определенные папки, но безуспешно. Я немного потерян в том, что мне здесь использовать? PendingIntent? Использовать метод createWriteRequest()? Я не нашел ни одного пошагового руководства по этой теме. Я прочитал, что мне нужно запрашивать разрешение для каждого файла, чтобы иметь возможность его модифицировать. Но как другие приложения делают это без каких-либо осложнений? (Например, в TotalCommander я могу легко переименовать файл) Не могли бы вы показать простой код, как это обработать?

SDK 33
Android 14

Манифест:

    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

Я храню в переменной lastModifiedTime временной код ссылки.

И сначала попробовал простой процесс переименования в ту же директорию:

Активность:

        String path = Environment.getExternalStorageDirectory().toString()+"/DCIM/Camera";
        Log.d("Files", "Path: " + path);
        File directory = new File(path);
        File[] files = directory.listFiles(File::isFile);
        if (files != null){
            for (File file : files){
                if (file.lastModified() > lastModifiedTime){
                    Log.d("Files", file.getName());
                    File newfile = new File(path+"/"+file.getName()+"_2");
                    Log.d("Files", "new: "+newfile.getName());
                    if (file.renameTo(newfile)){
                        Log.d("Files", "OK");
                    } else {
                        Log.d("Files", "ERROR");
                    };
                }
            }
        }

Ответ или решение

Для переноса изображений из каталога DCIM/Camera в другой каталог на Android 14 (SDK 33) необходимо учитывать особенности работы с файловой системой и разрешениями в более поздних версиях Android. Ваша цель – перемещать файлы в указанные каталоги, созданные другими приложениями, что требует особого внимания к управлению разрешениями и использованию новых API.

Ниже приведен шаг за шагом подход к реализации данной задачи.

Шаг 1: Получение разрешений

Так как ваши действия требуют чтения и записи файлов, убедитесь, что вы запросили необходимые разрешения в AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.MOVE_MEDIA" />

Обратите внимание, что в Android 14 вам может понадобиться использовать Storage Access Framework (SAF) для работы с файлами на внешнем хранилище.

Шаг 2: Запрос разрешений во время выполнения

Перед выполнением операций с файлами необходимо запросить разрешения. Это можно сделать с помощью библиотеки ActivityCompat:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_MEDIA_IMAGES}, REQUEST_CODE);
}

Шаг 3: Использование Storage Access Framework

  1. Открытие DocumentTree: Используйте ACTION_OPEN_DOCUMENT_TREE, чтобы позволить пользователю выбрать папку, куда вы планируете переместить изображения.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);
  1. Обработка результата: В методе onActivityResult() получите Uri выбранной папки.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_OPEN_DIRECTORY && resultCode == RESULT_OK) {
        Uri directoryUri = data.getData();
        // Сохраните uri для последующего использования
    }
}

Шаг 4: Перемещение файлов

С помощью ContentResolver вы сможете переместить файлы по следующему примеру:

private void moveFile(Uri srcUri, Uri destUri) {
    try {
        InputStream inputStream = getContentResolver().openInputStream(srcUri);
        OutputStream outputStream = getContentResolver().openOutputStream(destUri);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, length);
        }

        outputStream.flush();
        outputStream.close();
        inputStream.close();

        // Удаление старого файла
        getContentResolver().delete(srcUri, null, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Шаг 5: Реализация логики перемещения

Теперь вы можете реализовать логику в вашем приложении, чтобы перемещать только те файлы, которые вам нужны:

String path = Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera";
File directory = new File(path);
File[] files = directory.listFiles(File::isFile);
Uri destUri = ...; // Полученный ранее Uri

if (files != null) {
    for (File file : files) {
        if (file.lastModified() > lastModifiedTime) {
            Uri srcUri = Uri.fromFile(file);
            Uri newDestUri = destUri.buildUpon().appendPath(file.getName()).build();
            moveFile(srcUri, newDestUri);
        }
    }
}

Завершение

Следуя этим шагам, вы сможете эффективно перемещать изображения из DCIM/Camera в любое другое местоположение, на которое у вас есть разрешения. Использование Storage Access Framework поможет вам избежать проблем, связанных с ограничениями памяти и разрешениями на более современных версиях Android.

Оцените материал
Добавить комментарий

Капча загружается...