Fileprovider android что это

Share Files Using FileProvider on Android

Several weeks ago I was given a task to open an internal PDF file in any PDF reader application on an Android phone. I thought it would be straightforward, but things turned out to be complicated. Google’s documentation on FileProvider proved to be confusing and lacking concrete examples. Nevertheless, I knew I had to use ContentProvider to tackle the issue.

What is FileProvider

ContentProvider is an Android component which encapsulates data and provides it to other applications. It is required only if you need to share data between multiple applications. For example, the contacts data is shared with other applications using ContactsProvider which is a subclass of ContentProvider.

FileProvider is a subclass of ContentProvider. While ContentProvider is a component that enables you to securely share any kind of data, FileProvider is used specifically for sharing the app’s internal files. The FileProvider class is part of the v4 Support Library so make sure to include it in your project.

To make FileProvider work follow these three steps:

  • Define the FileProvider in your AndroidManifest file
  • Create an XML file that contains all paths that the FileProvider will share with other applications
  • Bundle a valid URI in the Intent and activate it

Defining a FileProvider

To define a FileProvider inside your AndroidManifest you need to be familiar with these attributes and elements:

  • android:authorities
  • android:exported
  • android:grantUriPermissions
  • android:name
  • subelement

If all of these seem extremely familiar, you’ll find your way around FileProvider a bit easier, otherwise I’ve prepared a detailed description of each attribute and its purpose.

android:authorities

You must define at least one unique authority. Android System keeps a list of all providers and it distinguishes them by authority. Authority defines the FileProvider just like the application ID defines an Android application.

In general, the Android System uses a specific URI scheme for ContentProviders. The scheme is defined as content:///

so the system will know which ContentProvider is requested by matching the URI’s authority with the ContentProvider’s authority.

android:exported

This attribute can easily be misused because its name is misleading. To understand this attribute, think of your FileProvider as a room with locked doors. If you set the value to true, you’ve basically opened your doors to everyone. Everything will work from your point of view, but you’ve just created a huge security issue as every other app will be able to use your FileProvider without being given permission.

This can teach you to never program by coincidence and always be aware of the side-effects of your code. Also, always define this attribute because the default value on SDK 16 and lower is true.

android:grantUriPermissions

If we continue thinking of a FileProvider as a locked room, then this attribute is used to give a temporary one-time key to an external app. This attribute allows you to securely share your app’s internal storage. All you have to do is add either FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION to the Intent that activates the component to open your app’s internal file. To use these flags set their value to true.

element can also have subelements. The only difference being that by using the attribute you can share anything inside your app’s internal storage, while subelements allow you to choose a specific data subset for sharing. To use subelements instead, set the value to false.

Читайте также:  Programming settings in android

subelement

This subelement must be defined when using the FileProvider. You have to define a path to the XML file which contains all data paths your FileProvider can share with external apps.

The XML file must have the

element as its root. The

element must have at least one subelement which can be one of the following:

  • — internal app storage, Context#getFilesDir()
  • — internal app cache storage, Context#getCacheDir()
  • — public external storage, Environment.getExternalStorageDirectory()
  • — external app storage, Context#getExternalFilesDir(null)
  • — external app cache storage, Context#getExternalCacheDir()

You might have noticed that they vary according to the app’s directory which they define.

Each element must have a path and a name attribute. The path attribute defines the subdirectory you want to share and it does not support wildcards. The name attribute is used for security reasons and it will replace your subdirectory name with its value.

android:name

We set this value to android.support.v4.content.FileProvider.

Once you have defined a FileProvider in your AndroidManifest file, you are finally ready to use it. To share a file you have to create an Intent and give it a valid URI. The URI is generated using the FileProvider class.

Code implementation

AndroidManifest.xml

Notice that I’m using the app’s ID for authority. That’s because I have multiple flavors in the project and they can be installed on the device at the same time. Android System won’t let you install multiple applications with the same FileProvider so each flavor needs an unique authority.

file_provider_paths.xml

By defining paths like this, I allow the FileProvider to share all files that are inside the app’s internal cache and files directory.

Use your FileProvider

Once you understand how it works, implementing your own FileProvider is truly simple.

The complexity of the problem is not the code itself, but the documentation and understanding of how everything is interconnected. I hope this article will help you implement the FileProvider for your own use case and make the official documentation easier to read.

Источник

Организация обмена файлами

Для безопасной передачи файла из одного приложения в другое, необходимо настроить работу с URI файлов. Компонент FileProvider генерирует URI для файлов, основываясь на настройках в файле манифеста. В данном уроке рассказывается как добавить FileProvider в приложение и указать файлы, которые вы желаете передавать.

Примечание: класс FileProvider это часть библиотеки поддержки v4. Подробную информацию о библиотеке поддержки читайте в соответствующем разделе.

Указание объекта FileProvider

Для определения объекта FileProvider требуется добавить запись в файл манифеста. Эта запись дает право генерировать URI для данных, а так же содержит имя XML файла, в котором указано какими файлами может поделиться ваше приложение.

Следующий пример показывает, как добавить элемент

в манифест, чтобы определить объект FileProvider, authority и имя XML файла:

В данном примере, атрибут android:authorities описывает URI authority (в данном примере com.example.myapp.fileprovider ), который вы можете использовать для генерации URI с помощью FileProvider. В ваших собственных приложениях, authority состоит из значения android:package вашего приложения и строки “fileprovider”. Чтобы узнать больше о значении authority, смотрите раздел URI данных и документацию по атрибуту android:authorities.

указывает на XML файл, описывающий директории, которыми вы хотите поделиться. Атрибут android:resource это путь и имя файла, без расширения .xml . Содержимое этого файла мы рассмотрим в следующем разделе настоящего урока.

Указание общих директорий

После добавления объекта FileProvider в манифест, необходимо указать директории, содержащие файлы, которыми вы готовы поделиться. Для указания директорий создайте файл filepath.xml в директории res/xml вашего проекта. В файле добавьте XML элементы для каждой директории. Далее приведен пример файла filepath.xml , который показывает как поделиться подкаталогом директории files/ из вашего внутреннего хранилища:

В данном примере, тег содержит каталоги, лежащие внутри директории files/ вашего внутреннего хранилища. Атрибут path указывает на подкаталог images/ из каталога files/ . Атрибут name говорит объекту FileProvider добавить сегмент myimages в URI для файлов из каталога files/images/ .

Читайте также:  Обои 540x960 для андроид

может включать несколько вложенных элементов, указывающий на разные директории. В дополнение к элементу , вы можете использовать элемент для указания директорий из внешнего хранилища, а также для указания директории временных файлов. Чтобы узнать больше о вложенных элементах, смотрите раздел FileProvider.

Примечание: XML файл это единственный способ указать директории, которыми вы хотите поделиться. Вы не можете указать директории программно.

Теперь у вас есть полная спецификация FileProvider для генерации URI файлов из директории files/ вашего внутреннего хранилища или из ее поддиректорий. При генерации URI для файла в него будет добавляться значение authority, которое вы указали в элементе

Источник

FileProvider

java.lang.Object
android.content.ContentProvider
android.support.v4.content.FileProvider

Class Overview

FileProvider is a special subclass of ContentProvider that facilitates secure sharing of files associated with an app by creating a content:// Uri for a file instead of a file:/// Uri .

A content URI allows you to grant read and write access using temporary access permissions. When you create an Intent containing a content URI, in order to send the content URI to a client app, you can also call Intent.setFlags() to add permissions. These permissions are available to the client app for as long as the stack for a receiving Activity is active. For an Intent going to a Service , the permissions are available as long as the Service is running.

In comparison, to control access to a file:/// Uri you have to modify the file system permissions of the underlying file. The permissions you provide become available to any app, and remain in effect until you change them. This level of access is fundamentally insecure.

The increased level of file access security offered by a content URI makes FileProvider a key part of Android’s security infrastructure.

This overview of FileProvider includes the following topics:

Defining a FileProvider

Since the default functionality of FileProvider includes content URI generation for files, you don’t need to define a subclass in code. Instead, you can include a FileProvider in your app by specifying it entirely in XML. To specify the FileProvider component itself, add a

element to your app manifest. Set the android:name attribute to android.support.v4.content.FileProvider . Set the android:authorities attribute to a URI authority based on a domain you control; for example, if you control the domain mydomain.com you should use the authority com.mydomain.fileprovider . Set the android:exported attribute to false ; the FileProvider does not need to be public. Set the android:grantUriPermissions attribute to true , to allow you to grant temporary access to files. For example:

If you want to override any of the default behavior of FileProvider methods, extend the FileProvider class and use the fully-qualified class name in the android:name attribute of the

Specifying Available Files

element. For example, the following paths element tells FileProvider that you intend to request content URIs for the images/ subdirectory of your private file area.

element must contain one or more of the following child elements:

Represents files in the files/ subdirectory of your app’s internal storage area. This subdirectory is the same as the value returned by Context.getFilesDir() . Represents files in the root of your app’s external storage area. The path Context.getExternalFilesDir() returns the files/ subdirectory of this this root. Represents files in the cache subdirectory of your app’s internal storage area. The root path of this subdirectory is the same as the value returned by getCacheDir() .

These child elements all use the same attributes:

name=»name» A URI path segment. To enforce security, this value hides the name of the subdirectory you’re sharing. The subdirectory name for this value is contained in the path attribute. path=»path» The subdirectory you’re sharing. While the name attribute is a URI path segment, the path value is an actual subdirectory name. Notice that the value refers to a subdirectory, not an individual file or files. You can’t share a single file by its file name, nor can you specify a subset of files using wildcards.

Читайте также:  Мистер бин для андроид

You must specify a child element of

for each directory that contains files for which you want content URIs. For example, these XML elements specify two directories:

element and its children in an XML file in your project. For example, you can add them to a new file called res/xml/file_paths.xml . To link this file to the FileProvider, add a element as a child of the

element that defines the FileProvider. Set the element’s «android:name» attribute to android.support.FILE_PROVIDER_PATHS . Set the element’s «android:resource» attribute to @xml/file_paths (notice that you don’t specify the .xml extension). For example:

Generating the Content URI for a File

To share a file with another app using a content URI, your app has to generate the content URI. To generate the content URI, create a new File for the file, then pass the File to getUriForFile() . You can send the content URI returned by getUriForFile() to another app in an Intent . The client app that receives the content URI can open the file and access its contents by calling ContentResolver.openFileDescriptor to get a ParcelFileDescriptor .

For example, suppose your app is offering files to other apps with a FileProvider that has the authority com.mydomain.fileprovider . To get a content URI for the file default_image.jpg in the images/ subdirectory of your internal storage add the following code: As a result of the previous snippet, getUriForFile() returns the content URI content://com.mydomain.fileprovider/my_images/default_image.jpg .

Granting Temporary Permissions to a URI

Permissions granted in an Intent remain in effect while the stack of the receiving Activity is active. When the stack finishes, the permissions are automatically removed. Permissions granted to one Activity in a client app are automatically extended to other components of that app.

Serving a Content URI to Another App

There are a variety of ways to serve the content URI for a file to a client app. One common way is for the client app to start your app by calling startActivityResult() , which sends an Intent to your app to start an Activity in your app. In response, your app can immediately return a content URI to the client app or present a user interface that allows the user to pick a file. In the latter case, once the user picks the file your app can return its content URI. In both cases, your app returns the content URI in an Intent sent via setResult() .

You can also put the content URI in a ClipData object and then add the object to an Intent you send to a client app. To do this, call Intent.setClipData() . When you use this approach, you can add multiple ClipData objects to the Intent , each with its own content URI. When you call Intent.setFlags() on the Intent to set temporary access permissions, the same permissions are applied to all of the content URIs.

Note: The Intent.setClipData() method is only available in platform version 16 (Android 4.1) and later. If you want to maintain compatibility with previous versions, you should send one content URI at a time in the Intent . Set the action to ACTION_SEND and put the URI in data by calling setData() .

More Information

To learn more about FileProvider, see the Android training class Sharing Files Securely with URIs.

Источник

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