Как получить полный доступ к файлам во внешней памяти Android 11?
В Android 11 метод getExternalStorageDirectory, возвращающий путь до внешней памяти, является deprecated. Вместо него появились новые API для работы с конкретными публичными папками или папкой приложения.
Но по рабочей задаче мне надо работать с папками и файлами, лежащими в корне внешней памяти. Я не нашёл пример нового API, который бы позволял это делать. В документации Google есть по факту только как получить разрешение (через ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION), с этим проблем нет. Помимо работы с файлами из Kotlin мне так же надо взаимодействовать с файлами из C++. С устаревшим API проблем нет, там полные пути к файлам можно получить и делай с ними что хочешь. Но как быть с новыми API? Или забить и пользоваться старым, надеясь что в ближайших версиях его не выпилят?
PS В маркет приложение не пойдёт, поэтому я могу получать любые разрешения и делать всё, что захочу.
Евгений Шатунов, помимо работы с файлами в Kotlin мне надо так же работать с ними в NDK на C++. Соответственно я должен в NDK так же как-то универсально получить путь к корню внешней памяти и чтобы это решение не использовало deprecated методов, если это возможно.
Vlad, спасибо, ты это написал человеку, который занимается разработкой под Android со стороны C++ начиная еще с Android 2.0. Я NDK и саму ось знаю и использую уже 10 лет к ряду.
Евгений, интерфейсы NDK изложены на C, а Android базируется на модификации Linux, который тоже на C.
Почему бы тебе не добавить сюда еще тег C?
Или попробуем чем-то иным руководствоваться при выборе тегов?
Чисто к слову. Я знаю ответ на вопрос. Но я не буду отвечать потому что не помогаю создавать ПО для мошенничества.
Евгений Шатунов, ну да, только мошенникам же такое надо. Я работаю в компании, занимающейся разработкой телекоммуникационного ПО для различных заказчиков (не частников). И эта задача как раз рабочая.
Изменил на C.
PS меня интересует ответ на вопрос, а не ваша реклама самого себя. И я не припомню чтобы мы переходили на ты.
Евгений, я всегда и со всеми на ты, а у тебя нет обоснования культурной ценности обращения "на вы". Ты ведь даже не в курсе истории этой формы обращения.
Ответ на твой вопрос полезен в основном и только тем, чье ПО потом будет воровать важные данные у простых людей.
Евгений Шатунов, может вы тогда с высоты своего "величия" соблаговолите ответить тогда на такой вопрос - если я буду использовать публичную папку для своего приложения (ту же Documents на внешней памяти) с новым API, то как мне получить в этом случае доступ к этой же папке из C и создавать/дозаписывать файлы? Это не потребует тогда разрешения MANAGE_EXTERNAL_STORAGE и я не смогу ничего ни у кого "своровать".
Олег, с разрешениями и старым API проблем нет. Что в 10, что в 11 папки, файлы создаются и можно писать в них. Вопрос именно про новое API, где все примеры это доступ к общим папкам или папке приложения.
Евгений , старое апи не выпили. А просто сделали для него новый отдельный пермишен.
Ужесточили модерацию. Запретили костыль, который был в 10ке.
Я вынес функцию требующею такого доступа в отдельный продукт.
Проходил модерацию по ветке. Пермишен требуется для основной функции приложения. Приложение является средством автоматизации работы с файлами.
Олег, но где гарантии что они в следующих версиях не выпилят? На маркет мне в данном случае пофиг, так что в целом могу делать что захочу. Старое API работает, так что скорее всего пока что придётся использовать его, а потом наверное буду думать есть ли смысл запариваться с новым.
Про новое разрешение я в курсе, в основном вопросе я упоминал что сделал его получение.
Евгений, В папке своего приложения можешь делать что угодно .
Если часть кода написанная на C++ не умеет работать с content: провайдерами,
то кешируй в локальном кеше приложения getCacheDir() и работай с ним.
Запросить файл
private final ActivityResultLauncher<String> mGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
this::PdfFileSelected);
private void StartPdfChoice() {
try {
mGetContent.launch("application/pdf");
} catch (android.content.ActivityNotFoundException ex) {
showToast(getString(R.string.need_external_fm));
}
}
private void PdfFileSelected(Parcelable p) {
if (!(p instanceof Uri)) {
p = Uri.parse(parcelable.toString());
}
// дальше асинхронно кешируешь и делаешь, что там дальше требуется
}
Все просто, если файл нужно открыть по кнопке или поймать интент с ним.
Сложности с тем, чтобы автоматически отслеживать изменения файлов в директориях.
Олег, из-за специфики ПО никаких вопросов быть не должно. Вся работа с файлами (собственного расширения) происходит в фоне невидимо для пользователя. Он только потом можно посмотреть историю из сохраненных файлов. Ну и из-за того, что в дальнейшем эти файлы считываются уже готовым ПО на ПК через MTP, то крайне нежелательно куда-то переносить в другое место относительно уже существующих путей в корне внешней памяти.
И так как основной источник данных у меня будет написан в NDK, то не хотелось бы через JNI дергать сохранение в файл много раз в секунду.
Евгений, переходите на ардуинки. Так как если думать чего там в андроид еще плохого придумают дело бесполезное. Автоотзыв критических разрешений уже придумали. Не проверял. Достаточно нотифи в шторке или требуется явный лаунч интент, чтобы пермишен не отозвали.
Олег, ну перезапросить разрешение не проблема. Ардуинка к сожалению не вариант, только телефон на Android. Ладно, пофиг, сделаю через старое API, а там если что буду переделывать :-D