Android что такое fileprovider

FileProvider

In the previous series of articles we looked at DownloadManager and saw that DownloadManager actually handles the sharing of downloaded content with other apps. But what if we actually need to do this and we’re not using DownloadManager? A common case for such things would be if we either want to share content with other apps or, as in the example in the previous series, the content was in a format that our app didn’t support so we wanted to defer the displaying of that content to another app on the device which did support the content type – in the example this was PDF. In this article we’ll explore why this can be problematic and look at FileProvider which enables us to quite simply do exactly what we need to.

Let’s first consider why sharing files can be problematic. The most obvious place for us to store content is in the app’s private storage area (using Context#openFileOutput() ), or possibly the internal cache (using Context#getCacheDir() ). The one aspect that both of these locations share is that they are only accessible to our app. While this may be good for security, it poses a problem if we wish to defer the displaying of the content to another app, such as with our PDF example. The obvious way to overcome this would be to use external storage using, for example but not limited to, Environment#getExternalStorageDirectory() or Environment#getDownloadCacheDirectory() .

This poses two potential problems. Firstly the content will be publicly accessible to all apps and, depending on the nature of our app, we may want to limit which other apps can actually access the data. The second problem is rather more subtle. In order for our app to read and write to external storage we’ll need the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE . If we then share content which we’re stored on external storage using a file://. URI then the app which is given responsibility to display that content must also have the READ_EXTERNAL_STORAGE permission otherwise it will not be able to actually read the content. We should not make assumptions about what permissions other apps may hold – this can olnly cause problems.

It is for this reason that simply sharing content via file://. URIs is not a good idea.

So what’s the alternative? The standard mechanism supported by Android is to define a ContentProvider which can expose content using a content://. URI, and the app sharing the content (i.e. our app) retains the responsibility for how and where the content is stored. Anyone who has ever implemented a ContentProvider will be aware that they can require a bit of work to implement. However, there is a simpler way: FileProvider.

FileProvider is in the v4 support library (so there’s really no excuse not to use it!) and enables us to create a ContentProvider which will share files with very little effort.

Let’s look at the differences between a file://. URI and a content://. one. The file://. URI representing the content in the sample app accompanying this post is file:///data/user/0/com.stylingandroid.fileprovider/cache/pdf-sample.pdf and the content://. URI is content://com.stylingandroid.fileprovider/my_files/pdf-sample.pdf . The file://. URI desribes an absolute position within the file system of the device, whereas the content://. URI identifies the package name of the app ( com.stylingandroid.fileprovider ) along with some identification of the content itself which is relevant only to the app itself.

The MainActivity from the sample app needs to share some content which has been stored in the internal cache directory. I won’t bother listing the full source here and providing a full explanation as it is fairly straightforward. We’ll focus on how we can share that content.

The first thing that we need to do is declare the FileProvider in our Manifest:

Источник

How To Use Android FileProvider To Share Files Between Apps

Android FileProvider is a sub class of ContentProvider. It is used to share files between different android apps. It is implemented in android v4 Support Library. So before use it please make sure that you have include supported library in android project build.gradle file as below.

1. FileProvider Benefits.

Using FileProvider you can make your app files more secure in following ways.

  1. You can fully control which file to share to which app more accurately.
  2. Your app do not need to ask user to grant WRITE_EXTERNAL_STORAGE permission always. This can make your app more user friendly.
  3. When your app destroy, the shared folder permission will also be revoked. Then other apps can not access those files later.

2. Create FileProvider Steps.

  1. Declare FileProvider provider component in AndroidManifest.xml file.
  2. Create a share folder xml file to indicate which folder will be shared.

2.1 Define FileProvider In AndroidManifest.xml.

Please add below provider definition in Android project AndroidManifest.xml first to use FileProvider.

FileProvider Attributes Explain.

  1. android:authorities : Authority values must be unique, it is used by android system to distinguish all providers. It is also used in FileProvider accessing uri such as content:///

because FileProvider is a sub class of ContentProvider. You can use $ as authority value, it will use your app package name automatically. And each app package name in android is unique.

  • android:name : This attribute value must be android.support.v4.content.FileProvider
  • android:exported : This attribute value must be false, because if set it to true then all other apps can use this FileProvider without grant permission. So this will raise security risk. If you set it’s value to true a SecurityException( “Provider must not be exported” ) will be thrown.
  • android:grantUriPermissions : This attribute value must be true. This means you need to grant uri read / write permission to other apps that can access your shared files. You can use intent setFlags method to grant FileProvider access permission to other apps like below.

    If you set grantUriPermissions value to false, it will throw SecurityException( “Provider must grant uri permissions” ).

  • meta-data sub element : The provider meta-data sub element is used to specify the shared folder definition xml file. It has two attributes android:name and android:resource.android:name value must be android.support.FILE_PROVIDER_PATHS and android:resource value is a xml file name, the name can be any value but it should be located in app / res / xml folder.
  • 2.2 Define Shared Folder In Xml Resource File.

    In our example the shared folder definition xml file name is shared_file_paths.xml, below is it’s content. You can see comments for each element explanation.

    From above example, we can see that you can share both root, internal, external folders in android. To share different type folder use different xml tag.

    Each tag has two attributes, name and path, name attribute value is the path value in the FileProvider uri when it is accessed by other apps.

    For example if name value is “share”, then the FileProvider uri should be something like content:// /share/abc.png. This way the real local file path will not exposed to other apps.

    3. How To Use FileProvider In Code.

    Below is the general usage about how to use FileProvider.

    1. Create a new Intent object.
    2. Set intent flag to grant read / write uri permissions to startup activity.
    3. Use FileProvider to get shared file uri.
    4. Start the activity use above intent. Then the started activity can write the shared files through FileProvider.
    5. To operate files through FileProvider, you should use ContentResolver and the file uri together.
    6. Use below code to grant uri permissions to all activities which will be started by this intent.

    Источник

    Learn how to use fileprovider in Android with example

    Today we will be looking at the one of the confusing topic in android i.e. FileProvider. It is confusing for beginners as they do not understand, how to use it and why to use it. So let us learn how to use FileProvider in Android with an example project.

    If you just want to get file path from internal document picker check out this article: here.

    What is a FileProvider in Android ?

    How long have you been exploring this concept of file provider in android ? I think it’s been quite a while but you have not found a easier explanation about it. Here I will simply explain what a fileprovider is and why even bother with it in the first place ?

    FileProvider is simply a special subclass of ContentProvider which allows manipulating user data on storage more secure and easy ( not really at first ). It simply creates a content:/// URI instead of file:/// which makes secure.

    How does it make the files accessing more secure ? To answer that question we must understand that using the FileProvider only a content:/// is exposed meaning the actual file location is hidden, and adds security.

    But adding security means some headaches for developers especially for someone who is just starting with the Android Development. I will break down BITS of FileProvider below so let us continue.

    Using FileProvider in Android application

    Let us see how we can use the FileProvider in our application step by step.

    Setting up FileProvider in manifest

    Let us see how we can add the FileProvider definition in out manifest file. Add the code below in your AndroidManifest.xml file.

    Creating file_paths.xml file to add our file paths

    Now that we have added the FileProvider definition in our AndroidManifest.xml let us look at the code.

    You will receive an error at the code above because we have to mention the path for the FileProvider to access. Which we will do below but first lets create an Android resource directory.

    Go to projects side bar and navigate to app > res . Right click there and click Android Resource Directory . name the directory xml and select xml from drop down.

    After that create the file_paths.xml in the xml directory and add the contents below.

    Confused about what the code above means ? Don’t be because I will break everything down.

    Understanding what each file path actually mean

    Now we have to understand something before proceeding. Everything is scoped with file paths. Meaning accessing anything outside defined file paths will cause a runtime exception.

    Each type of paths you see between

    serve a purpose. And we are going to learn what that is with this fileprovider Android example.

    Note: name and path is same for each. where name is the pointer and path is the actual location.

    This is the path will will be accessible by invoking this method Context.getFilesDir() . We will get a file instance pointing to the files dir. This directory is located in the internal storage area on your device.

    Same as above the only difference is it resides in the external removable storage area of the device. The root path is returned by Context.getExternalFilesDir(null) .

    />

    This is same as files-path but it provides the root directory for internal area cache. Which is what you get when you invoke Context.getCacheDir() .

    Same as the the local cache but the difference is the cache directory is located in external storage area. Which you will get once you use Context.getExternalCacheDir().

    This path also defines the media directory located on the external storage area of your device. Which returns the path provided by Context.getExternalMediaDirs() . But this method is deprecated and MediaStore must be used.

    This path is relative to the external root of your device. And you can get this file by Environment.getExternalStorageDirectory() . As you normally would, this method is marked deprecated and must not be used normally. Always use file providers for any file reading.

    Getting the content URI

    Now that we have understood what each means. Let us move forward and retrieve out URI, as it was our main goal.

    We have set everything up let us create a temporary file in our cache directory. Let us write the code in out MainActivity as

    Now that will create a file named test_file.txt in our cache directory, remember ?

    Next we will update the URI into our TextView just to make sure it worked.

    Look at the FILE_AUTHORITY which we have declared in the companion object block. The full code for MainActivity is provided below:

    Sharing the URI using ShareCompat.IntentBuilder

    Let us explore how we can share the URI using the ShareCompat.IntentBuilder here.

    This will open up the possible applications for image/jpg , you can change that as per your need.

    Now we are done. What you do with the URI is up to you. Next time we will learn how to get the actual file from URI. Till then, keep learning.

    For reference you can checkout official documentation, here.

    Источник

    How to get away with READ/WRITE permissions on Android

    Android has been using permissions since its beginning but never really enforced the correct usage until Marshmallow and developers took advantage of it and went rampant. Since Marshmallow (API 23, Android 6.0), android ecosystem introduced permission requests and now we have to ask user to explicitly provide permissions which is really good in the sense of privacy for the users, but adds a lot of work for developers and provides kind of bad user experience.

    This article has a bit of a clickbait title and does not focus on any hacks but leverages Android’s ecosystem to show how an app can read, write and share files without requiring READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE . Each app in Android runs in its own system, like a sandbox. These sandboxes are not connected from one another which provides security. Now, to work with other apps, Android system has provided certain tools and one of them is FileProvider. FileProvider is a special subclass of ContentProvider that facilitates secure file sharing with other apps by creating content:// uri. We will come back to this later.

    Note: This post is not intended towards Read/Write heavy files such as a photo gallery or a music player. If your app occasionally write a file, eg. export some file or save an image once in a while, you may find this interesting.

    Let’s begin by checking what different methods and storage options we have to create a file.

    Create a file

    As the title says, you don’t need to have WRITE_EXTERNAL_STORAGE permission to create a file and write to it. If you use app’s internal storage to write a file, you don’t need write permission.

    Write to internal storage

    Files in your app’s internal storage are private and secure from other apps. On Android 6.0 and lower, other apps can read your app’s internal files if you set the file mode to world readable. This mode has been deprecated and will throw a SecurityException from Android 7.0. To share an internal file, you need to use FileProvider .

    Create a file in internal storage — context.getFilesDir() returns a File representing an internal directory of your app.

    You may also use context.openFileOutput() to get a FileOutputStream to write.

    Read more about writing to internal storage on Android docs — Write to internal storage

    Write to cache

    App’s cache directory is uniquely associated with the app. This directory is meant for temporary storage and the system may delete the files if running low on storage.

    Write to external storage

    Now, coming to the most important part. We can write to external storage without asking for WRITE_EXTERNAL_STORAGE permission. Android 4.4 (API 19) introduced Storage Access Framework (SAF) which makes it simple for users to browse and open documents, images, and other files across all of their their preferred document storage providers. We’ll use SAF to create a new file and write to it.

    This intent will trigger Storage Access Framework and the user will see a document browser prompting user to save the file. Once user saves the file, the app gets callback with uri of the file. mimeType will depend on what type of file you’re going to write. eg. txt/plain for a text file, image/png for a png image, application/pdf for a PDF, etc.

    The Storage Access Framework creates a new file with the given name and provides your app with a uri generated from FileProvider. Your app gets temporary access to write to this file (via uri). We can use FileDescription to write to this file.

    That’s it! You have created a file in external storage and written to it without asking user for storage permissions. Read more about SAF on android docs — Document Provider.

    Read a file

    To read a file from external storage, your app needs to have READ_EXTERNAL_STORAGE permission (or WRITE_EXTERNAL_STORAGE permission). But we can leverage Storage Access Framework, other apps (gallery, file explorer, etc) to let user a pick a file that they want to use. Reading from internal storage or cache directory does not require any system permissions.

    Reading from external storage

    mimeType is based on what type of file you want user to select. eg. txt/plain for a text file, image/png for a png image, application/pdf for a PDF, etc. This intent will trigger an application (or an app chooser) using which user can pick a file. This will return your app an uri generated from FileProvider and your app gets temporary access to read the file.

    If it’s a text file, reading the contents is very easy. context.contentResolver.openInputStream(uri).reader().readText()

    If it’s an image file, you can use FileDescriptior to convert to Bitmap.

    So yes, if you have an app which seldom reads from external storage, you may use this method to read files without requiring explicit permissions. Read more about Document Provider.

    Share a file

    Sharing some information from the app has become one of the most basic requirements and users want to share a lot of things with their friends, eg. a note, an image, something that they drew, etc. To improve security and also to make sure that other apps with which the content is being shared with has the correct permissions, Android introduced FileProvider. As mentioned above, FileProvider is a special subclass of ContentProvider that facilitates secure file sharing with other apps by creating content:// uri.

    Above we used other apps to create and read files from external storage. This is only possible because of FileProvider. Android does not allow sharing file:// uri and will immediately throw FileUriExposedExceptio which will crash the app. So when an app wants to share a file with other apps, the app creates a content uri using FileProvider, grants temporary read or write access to the other app (via intent) so that the other apps can have access to the file regardless if they have READ/WRITE permission or not.

    I think FileProvider is the single most useful feature in android ecosystem. FileProvider comes with support library so we don’t have to worry about OEM updates.

    Setup FileProvider

    Setting up FileProvider takes about 5 mins and once it’s done, you don’t have to worry about it at all.

    In your app’s AndroidManifest declare a provider.

    android:authorities attributes 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. Or you can just set it based on your app id. If you use $ , during the build, gradle will replace it with your actual app id, so if you have different build variants and flavors, this would avoid conflict of having multiple apps with same authority.

    Keep android:exported attribute as false as the FileProvider does not need to be public. Set the android:grantUriPermissions attribute to true, to allow you to grant temporary access to files.

    Specify available files

    In the meta-data you have to define what files are available through fileprovider for other apps to use. This does not mean that other apps have access to those files. Other apps will have access only when your app generates a content uri using FileProvider, shares it with the other apps via intent and grants uri permissions.

    Create a folder named xml in your app’s res directory and create a file named fileproviderpaths.xml . You may keep any name, just make sure that it’s reflected in the manifest.

    name provides path segment to uri which increases security as this value hides the name of the subdirectory that your app is sharing. path provides subdirectory that you are sharing. path value has to be a subdirectory. You can not share a file by its file name or using wildcards.

    There are different tags available for different types of storage.

    • is for internal storage subdirectory.
    • is for external storage subdirectory.
    • is for cache storage subdirectory.

    You can find more types of tags to specify files on Android docs — Specifying available files.

    Once this setup is done, we are ready to share files with other apps.

    Share files

    So, yeah. You have shared your file securely with other app and the other app has temporary access to your file via content uri.

    You should definitely read more about FileProvider and how cool it is on Android docs — FileProvider.

    As FileProvider often likes to say and I quote

    FileProvider is a really great concept and it works so well. You can request longer access to files using it and so much more.

    Epilogue

    I was adding support for offline export and import of data in my app — Flutter: Instant Movie Ratings (written in Kotlin, not Flutter), I added permission to manifest, did the whole shebang of asking permissions to write files. I really don’t like permissions so I google-fu’ed and found out about Storage Access Framework, DocumentProvider, FileProvider and re-did the whole import/export functionality and removed the permissions. The app request permission just for internet access.

    Redux architecture and Android

    Learn the Redux architecture and implement the clean architecture it in your Android codebase. This series of posts explores the depth of Redux and guides you through implementing the architecture in Kotlin for your android app.

    Источник

    Читайте также:  Rooting android smart tv
    Оцените статью