Android Scoped Storage with example
Android uses a file system similar to disk-based file systems on other platforms. Let’s take a look at the various ways you can save your app data
Type of Storage
App-specific storage: This is where you store files that are meant exclusively for your app’s use. You can choose between dedicated directories within the device’s internal storage or dedicated directories within external storage. If you have sensitive information that should not be accessed by other apps, it’s best to save it in the directories within internal storage.
Shared storage: If your app needs to share files with other apps, such as media, documents, or other files, you can store them in shared storage. This allows other apps to access and use those files.
Preferences: For storing simple, private data in the form of key-value pairs, you can use preferences. This is useful for saving basic information specific to your app.
Databases: If you have structured data that needs to be stored persistently, you can use a private database with the help of the Room persistence library. This allows you to organize and manage your data effectively.
When should you use Scoped Storage?
- Protect user privacy and security.
- Make it easier for users to manage their files.
- Avoid file clutter
Why you need to use Scoped Storage:
- An app that lets users take photos and videos.
- An app that lets users download files from the internet.
- An app that lets users create and edit documents.
Here is an easy-to-understand explanation of Scoped Storage:
- Before Scoped Storage: Apps could access all files on the device’s external storage, regardless of who created the files or where they were stored. This could lead to privacy and security problems, as well as file clutter.
- With Scoped Storage: Apps can only access files that they have created themselves or files that are in the public Downloads folder. This helps to protect user privacy and security, and it also makes it easier for users to manage their files.
“Let’s take a look at some common storage operations and learn how to perform them.”
- Select a File: To enable file selection in your app, you can use the ACTION_OPEN_DOCUMENT method. This opens the system’s file picker app, allowing users to choose the file they want to open. To ensure that only file types supported by your app are displayed, you can specify a specific MIME type.
const val PICK_PDF_FILE = 1
private fun openFile() {
val intent =Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
type = "application/pdf"
addCategory(Intent.CATEGORY_OPENABLE)
flags = flags or Intent.FLAG_GRANT_READ_URI_PERMISSION
}
startActivityForResult(intent, OPEN_FILE_REQUEST_CODE)
}
- Select a Folder: If you want to enable folder selection in your app, you can use the ACTION_OPEN_DOCUMENT_TREE intent instead of ACTION_OPEN_DOCUMENT. This allows users to select an entire folder rather than just a single file.
private const val OPEN_FOLDER_REQUEST_CODE = 2
private fun openFolderLocation() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
}
startActivityForResult(intent, OPEN_FOLDER_REQUEST_CODE)
}
- Create a File: If you want to allow users to save files in a specific location within your app, you can use the ACTION_CREATE_DOCUMENT intent.
private const val CREATE_FILE_REQUEST_CODE = 1
private fun fileCreate() {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_TITLE, "${fileName.text}.txt")
startActivityForResult(intent, CREATE_FILE_REQUEST_CODE)
}
- Download into the App folder:
checkSelfPermissionReadWrite(this)
checks if the app has permission to read and write to external storage. If the app does not have permission, then therequestPermissionForReadWrite(this)
method is called to request permission.
private fun requestPermissionForReadWrite(context: Context) {
ActivityCompat.requestPermissions(
context as Activity,
arrayOf(
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE
), PERMISSION_READ_EXTERNAL_STORAGE
)
}
downloadImageIntoAppFolder()
downloads the file into the app's Downloads folder. The downloadImageIntoAppFolder()
method takes care of all the details of downloading the file, such as creating the DownloadManager request, setting the download options, and enqueuing the request.
private fun downloadImageIntoAppFolder() {
try {
val file = File(
this.getExternalFilesDir(
null
),"SampleImageDemo.png"
)
if (!file.exists())
file.createNewFile()
var fileOutputStream : FileOutputStream? = null
fileOutputStream = FileOutputStream(file)
val bitmap = (image.drawable as BitmapDrawable).bitmap
bitmap?.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream)
Toast.makeText(applicationContext,"Download Successfully" +file.absolutePath
,Toast.LENGTH_LONG).show()
}catch (e : Exception){
}
}
Here are four things to remember during the implementation of scoped storage in Android Studio:
- Check the app’s target SDK version. Scoped Storage is only available for apps that target Android 10 (API level 29) or higher. If your app targets an earlier version of Android, you will need to update the target SDK version before you can use scoped storage.
- Use the
getExternalFilesDir()
method to get the app's private directory. ThegetExternalFilesDir()
method returns a File object that points to the app's private directory on external storage. This directory is only accessible to the app, so you can store sensitive data in this directory without worrying about other apps accessing it. - Use the
getDownloadsDir()
method to get the public Downloads directory. ThegetDownloadsDir()
method returns a File object that points to the public Downloads directory on external storage. This directory is accessible to all apps, so you should only store non-sensitive data in this directory. - Request permission to read and write to external storage if necessary. If you need to access files in the public Downloads directory, you will need to request permission to read and write to external storage. You can do this by calling the
checkSelfPermission()
method and then requesting permission if the app does not already have it.
I hope this helps! Let me know if you have any other questions.
“That’s all for this article. I hope you learned something new. If you have any other knowledge or information about this topic, please share it in the comments so that we can all learn together.”
You can check out the GitHub sample for the implementation here: