- URI (Uniform Resource Identifier)
- Координаты
- Номер телефона
- Контакты
- Преобразование файла: Uri в файл в Android
- 15 ответов
- Get File Path From URI in Android JAVA
- Utility Class to Get File Path From URI in Android
- How to use UriUtils class
- Android 11 — хранилище с заданной областью — невозможно использовать java.io.File даже после предоставления разрешений Uri
- 1 ответ
- Как использовать содержимое из Uri
- Что можно делать?
- Чего не стоит делать?
- Просто забрать путь
- Представить, что MediaStore знает, чего вы хотите
- Попробовать извлечь путь
- Как получить имя файла?
- Хорошо, тогда как мне получить расширение файла?
- Что делать, если мне нужно передать файл в библиотеку?
- Как долго я могу использовать Uri?
- Но что делать, если мне понадобится контент на более длительное время?
- Зачем столько боли?
URI (Uniform Resource Identifier)
URI — это специальный идентификатор, по которому можно определить абстрактный или физический ресурс. Самый понятный пример с URI — это обычная веб-страница. Возьмём к примеру страницу http://developer.alexanderklimov.ru/android/catshop/catshop.php. Данный адрес можно разбить на несколько частей:
- Scheme — http
- Scheme-specific part — //developer.alexanderklimov.ru/android/catshop/catshop.php
- Path — /android/catshop/
У протокола http есть и другие параметры, которые рассматривать не будем. Существует также протокол ftp, имеющий свои параметры. Ниже вы увидите другие примеры. Главное здесь — возможность определить нахождение ресурса по представленным данным.
Допустим, мы хотим загрузить видеоматериал в компонент VideoView. Само видео может находиться в ресурсах программы или на SD-карте. С помощью URI мы можем подсказать программе, откуда следует загрузить файл.
Например, если видеофайл playcat.3gp находится в папке /res/raw, то получить адрес для загрузки можно следующим образом:
Если файл хранится на внешней карточке, то код будет следующим (опустим правильное определение имени карточки):
У компонента VideoView есть метод setVideoURI(URI uri), в котором нужно указать объект класса URI:
Посмотрим на другие примеры:
Координаты
Метод uri.getScheme() вернёт geo, а метод uri.getSchemeSpecificPart() — 54.354183,37.34011.
Номер телефона
В данном случае метод uri.getScheme() вернёт tel, а uri.getSchemeSpecificPart() — 1234578.
Контакты
URI также используется при работе с контент-провайдерами, в частности, с контактами.
Источник
Преобразование файла: Uri в файл в Android
какой самый простой способ конвертировать из file: android.net.Uri до File В Android?
пробовал следующее, Но это не работает:
15 ответов
то, что вы хотите.
Примечание: uri.toString() возвращает строку в формате: «file:///mnt/sdcard/myPicture.jpg» , тогда как uri.getPath() возвращает строку в формате: «/mnt/sdcard/myPicture.jpg» .
после долгого поиска это то, что сработало для меня:
EDIT: Извините, я должен был протестировать лучше раньше. Это должно сработать:
ничего из этого не работает для меня. Я нашел это рабочим решением. но мой случай специфичен для изображений.
непосредственно и скопируйте файл. См. также:
С Котлином еще проще:
Я сделал это следующим образом:
поэтому в основном сначала я пытаюсь использовать файл, т. е. снимок, сделанный камерой и сохраненный на SD-карте. Это не работает для изображения возвращаемых: Intent photoPickerIntent = новое намерение(намерение.ACTION_PICK); В этом случае необходимо преобразовать Uri в реальный путь по
@CommonsWare объяснил все вещи довольно хорошо. И мы действительно должны использовать предложенное им решение.
кстати, только на информацию мы могли положиться, когда quering ContentResolver — Это имя и размер файла, как указано здесь: получение информации о файле / разработчики Android
как вы могли видеть, есть интерфейс OpenableColumns который содержит только два поля: DISPLAY_NAME и SIZE.
в моем случае мне нужно было получить информацию EXIF о JPEG изображение и повернуть его, если это необходимо перед отправкой на сервер. Для этого я скопировал содержимое файла во временный файл с помощью ContentResolver и openInputStream()
Лучшим Решением
создайте один простой класс java FileUtil и используйте для создания, копирования и переименования файла
Я использую uri.toString() и uri.getPath() но не работает для меня. Я наконец нашел решение.
пользовательский класс FileUtil в вашем коде
вы можете получить файл из файла Uri, используя следующий метод. Он DocumentFile для параметра, но вы можете легко изменить его. Самый простой способ проверить этот метод для создания файла uri с помощью DocumentFile.fromFile(Environment.getExternalStorageDirectory()); который имеет Uri file:///storage/emulated/0
вместо создания файлов из Uri используйте DocumentFile.fromTreeUri(Context, Uri) или DocumentFile.fromSingleri(Context, Uri) для создания или удаления файлов и для потоков используйте getContentResolver().openOutputStream(documentFile.getUri()) и getContentResolver().openInputStream(documentFile.getUri()) для записи файлов и чтения файлов.
публичная строка getRealPathFromURI(Uri uri) <
затем, используя для получения файла из URI:
— НАДЕЖДА МОЖЕТ ПОМОЧЬ ВАМ — — — —
Android + Котлин
добавить зависимость для расширений Kotlin Android:
получить файл из uri:
Android + Java
просто переместить наверх 😉
следующим кодом я могу получить общий pdf-файл adobe application в виде потока и сохранить его в путь приложения android
для людей, которые ищут решение для изображений в частности вот это.
Источник
Get File Path From URI in Android JAVA
In Android when we pick an image, video, or any other type of file from the gallery, documents folder, or capture directly from the camera, we receive a URI object in intent. We have different ways to get a full file path from URI based on content providers. In this article, we will discuss how to get a file path from URI in Android for the coming files picked through Storage, Documents, as well as depending upon the _data field for the MediaStore and other file-based ContentProviders.
Following is the Java code if you are looking for Kotlin solution visit this Get Path From URI In Kotlin.
Utility Class to Get File Path From URI in Android
Create a file UriUtils.java and copy the following class in that file.
How to use UriUtils class
You might think that this class is too lengthy, but as mentioned above it handles all scenarios. It checks all android versions and the folders to what the Uri is appointing. It handles different types of content providers. There are different methods depending upon documents path, is it coming through downloads folder or media directory. It also checks is it picked through SECONDARY_STORAGE or EXTERNAL_STORAGE. Few other scenarios like Google Photos Uri, Google drive Uri are also handled properly. Just copy this class in your project as a utility class and rest will be handled by it.
That’s it. This is how to get file path from URI in Java Android.
Источник
Android 11 — хранилище с заданной областью — невозможно использовать java.io.File даже после предоставления разрешений Uri
В настоящее время я переношу приложение Android на Scoped Storage. Уход от java.io.file — это настоящий кошмар, и я чувствую себя большим недостатком. В настоящее время я пытаюсь понять, возвращаются ли пути getExternalMediaDirs() можно эффективно использовать с прямыми путями к файлам..
После запроса пользователя выбрать данную папку
И сохранение постоянных разрешений Uri на чтение / запись в onActivityResult
Ожидается ли, что по-прежнему не удастся использовать java.io.File в таком предоставленном пути ?
Эквивалент пути java.io.File
Некоторые заключительные примечания:
- такой путь можно записать с помощью SAF
- такой путь нельзя записать с прямым путем java.io.File (исключение EACCES )
- /Android/media/com.otherapp отличается от собственного /Android/media/com.app
- android.permission.MANAGE_EXTERNAL_STORAGE недоступен
1 ответ
Да, потому что после предоставления разрешений у вас будет доступ к Content Scheme Uri этой конкретной папки, а не к путям файловой системы, поэтому вы не сможете перечислить объекты java.io.File, используя этот Uri.
Но вы можете использовать его для listFiles() , который вернет вам список DocumentFile. Затем вы можете использовать эти объекты DocumentFile , чтобы получить Uri этого конкретного файла, используя documentFile.getUri (). Используя этот Uri , вы можете легко выполнять с этим файлом базовые операции, такие как display,copy,delete,share .
Ниже приведен пример списка файлов из папки другого приложения.
Я пропускаю часть кода для получения разрешений, предполагая, что у вас уже есть разрешения на доступ к папке этого другого приложения
В этом примере я перечисляю файлы из Android / media / com.whatsapp / WhatsApp / Media / .Statuses
После получения разрешения у нас есть дерево Ури
Здесь дерево Ури — это content://com.android.externalstorage.documents/tree/primary:Android/media
Этот каталог является DocumentFile, теперь он используется для перечисления всех папок внутри этого дерева Uri.
Теперь у нас есть список DocumentFile из папки другого приложения. Используйте Uri этого файла для дальнейших операций, таких как display,copy,delete,share .
Также прочтите комментарии к вашей точке зрения о Downloads папке but would this be the same matter for files in Download
Загрузки — это общедоступный каталог, я перечислил файлы, созданные моим собственным приложением с помощью listFiles (), и он вернул мне список Файл.
Источник
Как использовать содержимое из Uri
Поскольку становится всё более очевидным, что схема file прекращает своё существование, давайте рассмотрим, как всё это будет работать сейчас.
Посмотрим на такую ситуацию со стороны потребителя: вам передают Uri с каким-нибудь контентом в случае, когда раньше вы ожидали путь к файлу. Как вы будете получать этот контент?
Что можно делать?
Во-первых, убедитесь, что в любом месте, где у вас есть для схемы file, у вас также есть для content, с областью видимости для соответствующего MIME типа. Вы можете получить контент Uri другими способами (например, в onActivityResult()), но если вы поддерживаете файл-подобный контент для таких действий, как ACTION_VIEW, убедитесь, что вы поддерживаете как file, так и content Uri.
Следующим шагом поймите, какую роль играет Uri. Некоторые значения Uri указывают на записи базы данных, например, если вы предлагаете пользователю выбрать контакт. Такие случаи в данный момент нам неинтересны. Другие значения указывают на вещи, которые могут какими-то файлами — вот для этого мы и нужна эта статья.
Затем, если Uri имеет схему content, вы можете сделать следующее с экземпляром ContentResolver:
- Вызовите openInputStream() для чтения контента.
- Вызовите getType(), чтобы получить тип MIME данных.
- Вызовите query(), запрашивающий OpenableColumns, в котором вы сможете получить размер контента и некоторую разновидность отображаемого имени, связанного с контентом.
Первые два пункта напоминают, как вы обрабатываете http или https Uri, и поэтому, если у вас есть написанный для этого код, вы можете переписать его, чтобы избежать дублирования кода.
И это, в общем-то, всё.
Чего не стоит делать?
К сожалению, хотя и не всем нравится эти решение, но многие думают, что это единственный подходящий вариант.
Просто забрать путь
Некоторые разработчики вызывают getPath() у Uri, а затем пытаются открыть его как файл (например, new File(uri.getPath())).
Не делайте так!
Этот способ никогда не был надёжным, так как он предполагает схему file и то, что у вас есть прямой доступ к местоположению файла с заданным путём.
Если у Uri есть какая-либо другая схема, например content, путь в значительной мере становится бесполезным для вас.
Попытка выбрать какие-либо отдельные части из Uri и работать с ними вряд ли окажется успешной для вас.
Представить, что MediaStore знает, чего вы хотите
Некоторые разработчики пытаются запросить MediaStore для столбца DATA в надежде, что они смогут конвертировать Uri в путь к файлу.
Не делайте так!
Не каждый content Uri поступает из MediaStore. На самом деле, в настоящее время относительно немногие Uri так делают. MediaStore ничего не знает о значениях Uri от других поставщиков. Кроме того, даже если вы получите MediaStore Uri, который может индексировать медиа на съёмном носителе, у вас не будет доступа к файловой системе.
Попробовать извлечь путь
Некоторые разработчики используют более сложный вариант для вышеупомянутых подходов, с двумя тоннами кода, чтобы посмотреть на полномочия Uri и попытаться получить путь, основанный на эвристике, разработанной для разных полномочий.
Не делайте так!
Тот факт, что это возможно, является частичной ошибкой Google, поскольку они не сделали значения Uri более скрытыми.
Однако, этот способ тоже ненадёжен:
- Приложения могут менять свои структуры Uri, и поэтому эвристика, которая работает сегодня, может не работать завтра.
- Возможно, у вас не будет доступа к файлу, даже если вы определите путь.
- Скоро случится Кембрийский взрыв приложений, публикующих собственный контент, используя своих собственных поставщиков и значения Uri, благодаря запрету на схему file. Вам необходимо поддерживать этих поставщиков, поэтому вам необходимо использовать метод openInputStream() в любом случае.
Ниже представлен список вопрос, которые могут возникнуть в данной ситуации.
Как получить имя файла?
Вы не можете этого сделать.
Вы можете посмотреть последний сегмент Uri. Это может быть имя файла, а может и не быть. Нет требования, чтобы content Uri использовал реальное имя файла в качестве последнего сегмента пути.
DISPLAY_NAME, который вы можете получить из вышеупомянутого OpenableColumns, может быть именем файла, но также может и не быть. Термин «отображаемое имя» необязательно означает имя файла.
Кроме того, в зависимости от того, откуда контент идёт, фактически никакого файла может не существовать. Предположим. что кто-то в заметку с длинной записью в приложении для заметок, и это приложение делает её доступной через Uri для доступа к другим приложениям. Пользователь не создавал файл, не загружал, не делал ничего, связанного с файлами, с этой заметкой. Даже если для неё есть подлинное имя файла, оно не будет иметь никакого значения для пользователя.
Хорошо, тогда как мне получить расширение файла?
Вы не можете этого сделать.
Ещё раз, вы можете узнать, заканчивается ли Uri тем, что выглядит как имя файла. Нет никакого гарантии, что что-то вроде foo.bar будет являться файлом с расширением .bar.
Вы можете использовать MimeTypeMap или аналогичные виды преобразователей, чтобы попытаться получить MIME тип, который вы получаете из getType(), и затем получить расширение файла. Однако эти конвертеры обрабатывают только популярные MIME типы и не могут обработать кастомные.
Что делать, если мне нужно передать файл в библиотеку?
Во-первых, проверьте библиотеку на наличие в ней варианта InputStream с методом для файла, который вы хотите использовать. Если он есть, используйте InputStream.
Затем, рассмотрите замену библиотеку на ту, которая имеет вариант InputStream.
Наконец, создайте локальную копию контента, получив InputStream из ContentResolver, подучив FileOutputStream в локальном файле (например, внутри getCacheDir() для внутреннего хранилища) и используя операции ввода-вывода для копирования из InputStream в OutputStream. flush(), getFD.sync() и close() FileOutputStream, и теперь у вас есть файл. который вы можете передать в библиотеку.
Конечно, это копия контента, поэтому она может стать устаревшей. Этот способ хорош для одноразовой операции и подходит для случаев, когда вам законным образом нужна локальная копия файла.
Как долго я могу использовать Uri?
Предполагая, что на стороне провайдера ничего не происходит, Uri должен быть действителен в течение всего процесса, но после этого он может стать недействительным.
Представьте, что Uri является глубокой ссылкой на какой-нибудь контент, требующий аутентификации. URL, который вы получаете, является рабочим, поскольку пользователь прошёл аутентификацию. URL может быть полезен даже некоторое время, пока сеанс активен. Но в итоге сеанс завершится и URL станет бесполезным.
Но что делать, если мне понадобится контент на более длительное время?
Вы можете вызвать takePersistableUriPermission() в ContentResolver. Если провайдер предлагает удержать разрешения, и вы их принимаете, то система запомнит, что у вас есть доступ к Uri. Соблюдайте осторожность, вы можете использовать метод для неограниченного доступа к контенту бескончно или до тех пор, пока пользователь не переместит, удалит или сделает недоступным к контенту по старому Uri.
Проблема в том, что takePersistableUriPermission() не говорит вам, были ли получены разрешения. Вы должен будете вызвать getPersistedUriPermissions() и посмотреть, есть ли у вас разрешения. Возможно, здесь нет разрешений, которые можно удержать.
Другой вариант — сделать локальную копию, как было отмечено ранее в FAQ. Таким образом вы сможете контролировать свою копию. Это может потребовать некоторой корректировки вашего UI и терминологии. Вместо использования глаголов типа «перейти» (предполагая, что контент находится в другом месте), используйте «импортировать», «копировать», чтобы подчеркнуть тот факт, что содержимое копируется. Вы можете предложить функции «обновить», «заменить», чтобы пользователь смог получить свежий Uri, который вы можете использовать, чтобы заменить существующую локальную копию новой.
Зачем столько боли?
Видение Google заключается в том, что значения content Uri являются эквивалентом Android http / https в веб-приложениях: универсально понятные и используемые. В конце концов, ContentResolver может сделать этот контент доступным из:
- файлов, в том числе тех, к которым другие люди не имеют доступа.
- столбцов BLOB в базе данных.
- зашифрованных материалов, которые дешифруются на лету.
- материалов, которые хранятся в сети и должны быть загружены и сохранены в кеш.
- материалов, которые генерируются на лету.
Использование значений content Uri намного более гибкое и предлагает больше различных параметров безопасности.
Источник