Android file from content uri

How to convert a content Uri into a File

I know there are a ton of questions about this exact topic, but after spending two days reading and trying them, none seamed to fix my problem.

This is my code:

I launch the ACTION_GET_CONTENT in my onCreate()

retrieve the Uri in onActivityResult()

pass the Uri to another activity and retrieve it

The I have implemented this method based on another SO answer. To get the actual Path of the Uri

and in the Debug activity’s onCreate() I try to generate the file:

This is how the error looks like:

Caused by: java.lang.NullPointerException at java.io.File.(File.java:262) at com.dancam.lietome.Debug.onCreate(Debug.java:35)

When I run the app I get a NPE on this last line. The audio Uri, isn’t NULL though so I don’t understand from what it is caused.

I’d really appreciate if you helped me out.

This is the library I’m trying to work with.

Note: I know exactly what NPE is, but even debugging I couldn’t figure out from what it is caused in this specific case.

3 Answers 3

pass the Uri to another activity and retrieve it

Your other activity does not necessarily have rights to work with the content identified by the Uri . Add FLAG_GRANT_READ_URI_PERMISSION to the Intent used to start that activity, and pass the Uri via the «data» facet of the Intent ( setData() ), not an extra.

To get the actual Path of the Uri

First, there is no requirement that the Uri that you get back be from the MediaStore .

Second, managedQuery() has been deprecated for six years.

Third, there is no requirement that the path that MediaStore has be one that you can use. For example, the audio file might be on removable storage, and while MediaStore can access it, you cannot.

How to convert a content Uri into a File

On a background thread:

  • Get a ContentResolver by calling getContentResolver() on a Context
  • Call openInputStream() on the ContentResolver , passing in the Uri that you obtained from ACTION_GET_CONTENT , to get an InputStream on the content identified by the Uri
  • Create a FileOutputStream on some File , where you want the content to be stored
  • Use Java I/O to copy the content from the InputStream to the FileOutputStream , closing both streams when you are done

Источник

Creating file from Uri

I’m trying to upload a image to php, for that I need to send a File to the server. So I am trying to create a file from the data parameter.

But I got this error Cannot resolve constructor File

Here’s my code:

5 Answers 5

The appropriate way is to getContentResolver().openInputStream(uri_of_your_file); and using a FileOutputStream to your desired path and then use that file.

You can use ContentResolver and openInputStream() to get an InputStream on the content represented by the Uri. You can create a FileOutputStream on some file that you control. And, you can use Java I/O to copy from the InputStream to the OutputStream, making your own copy of the content in a file that you control.

Sample code for doing that,

Читайте также:  Как проверить оригинальный андроид или нет

@GeekDroid’s answer is correct, but I thought I would provide more info to help clarify.

I’ve created a class that will copy/create a new file inside your application’s directory. This is done on the background thread, as it should be done.

I have also created a callback interface to get the «status» and display a ProgressBar

Here is the interface(You can change the name and callbacks to whatever):

Here is the class to copy the file:

In your Activity you should do the following:

You can cancel the copying of the file at any time, by calling:

If you want to implement it exactly as I did and display a ProgressBar while the file is being copied, then here is the layout and style of my dialog:

Here is the dialog while the file is being copied:

Conclusion:

With the above, your file will be copied to /storage/emulated/0/Android/data/yourPackageName/files/Temp/YourFile.jpg . While the files are being copied a progress dialog will be displayed indicating the progress as a percentage (this is useful for when copying large files). If there was an error while copying the file, the reason will be provided in onCopyPostExecute

This will work with file and content Uri’s.

Источник

Convert file: Uri to File in Android

What’s the easiest way to convert from a file: android.net.Uri to a File in Android?

Tried the following but it doesn’t work:

22 Answers 22

What you want is.

Note: uri.toString() returns a String in the format: «file:///mnt/sdcard/myPicture.jpg» , whereas uri.getPath() returns a String in the format: «/mnt/sdcard/myPicture.jpg» .

directly and copy the file. Also see:

After searching for a long time this is what worked for me:

Android + Kotlin

Add dependency for Kotlin Android extensions:

Get file from uri:

Android + Java

Just move to top 😉

EDIT: Sorry, I should have tested better before. This should work:

URI is java.net.URI.

Best Solution

Create one simple FileUtil class & use to create, copy and rename the file

I used uri.toString() and uri.getPath() but not work for me. I finally found this solution.

Use FileUtil class in your code

None of this works for me. I found this to be the working solution. But my case is specific to images.

With Kotlin it is even easier:

If you have a Uri that conforms to the DocumentContract then you probably don’t want to use File . If you are on kotlin, use DocumentFile to do stuff you would in the old World use File for, and use ContentResolver to get streams.

Everything else is pretty much guaranteed to break.

For this case, especially on Android, the way going for bytes is usually faster.

With this, I solved it by setting up a class FileHelper which is given the responsibility to deal with reading/writing bytes from/to file through stream and a class UriHelper which is given the responsibility to figure out path of Uri and permission.

As far as it’s knew generally, string.getBytes((charset == null) ? DEFAULT_CHARSET:charset) can help us to transfer string you want to bytes you need.

How to let UriHelper and FileHelper you to copy a picture noted by Uri into a file, you can run:

Источник

Как использовать содержимое из Uri

Поскольку становится всё более очевидным, что схема file прекращает своё существование, давайте рассмотрим, как всё это будет работать сейчас.

Посмотрим на такую ситуацию со стороны потребителя: вам передают Uri с каким-нибудь контентом в случае, когда раньше вы ожидали путь к файлу. Как вы будете получать этот контент?

Что можно делать?

Во-первых, убедитесь, что в любом месте, где у вас есть для схемы file, у вас также есть для content, с областью видимости для соответствующего MIME типа. Вы можете получить контент Uri другими способами (например, в onActivityResult()), но если вы поддерживаете файл-подобный контент для таких действий, как ACTION_VIEW, убедитесь, что вы поддерживаете как file, так и content Uri.

Читайте также:  Map editor samp android

Следующим шагом поймите, какую роль играет 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 для доступа к другим приложениям. Пользователь не создавал файл, не загружал, не делал ничего, связанного с файлами, с этой заметкой. Даже если для неё есть подлинное имя файла, оно не будет иметь никакого значения для пользователя.

Читайте также:  Процесс com android phone был остановлен

Хорошо, тогда как мне получить расширение файла?

Вы не можете этого сделать.

Ещё раз, вы можете узнать, заканчивается ли 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 намного более гибкое и предлагает больше различных параметров безопасности.

Источник

Оцените статью