Вопрос или проблема
Я пытаюсь создать приложение для сортировки своих ранее сделанных фотографий на внешнем хранилище.
Я хочу переместить их в определенные папки, но безуспешно. Я немного потерян в том, что мне здесь использовать? 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
- Открытие DocumentTree: Используйте
ACTION_OPEN_DOCUMENT_TREE
, чтобы позволить пользователю выбрать папку, куда вы планируете переместить изображения.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);
- Обработка результата: В методе
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.