Skip to content

FileSystem

Danger

The filesystem and mediastore modules are deprecated. You should use the new storage module which is relying on Okio Filesystem API.

modernstorage-filesystem is a library abstracting storage interactions when using the Storage Access Framework by wrapping document uris in Path. It allows using methods from java.nio.Files without having to learn another API like DocumentFile.

java.nio is a non-blocking I/O API, available from API 26+ (Android Oreo). Popular libraries are already accepting Path as input such as Apache Commons, Google Guava and Okio.

Info

Not all java.nio.Files methods are supported yet. This guide highlights common supported ones.

Add dependency to project

modernstorage-filesystem is available on mavenCentral().

// build.gradle
implementation("com.google.modernstorage:modernstorage-filesystem:1.0.0-alpha03")

If your app minSdk is lower than API 26, you need to override the filesystem minSdk requirement in your app's manifest:

<!-- Don't forget to add the tools namespace (xmlns:tools) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.sample.app">

    <!-- Override API 26 minSdk -->
    <uses-sdk tools:overrideLibrary="com.google.modernstorage.filesystem" />

    <!-- ... -->
</manifest>

Info

modernstorage-filesystem is only available for API 26+ as Android adds support for java.nio.Files API from Oreo. For previous versions, you can request READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permissions to access the shared storage.

API reference

modernstorage-filesystem API reference is available here.

Initialize before usage

To interact with FileSystem, you need to initialize it first:

AndroidFileSystems.initialize(context)

Select a file using SAF

/**
 * We register first an ActivityResult handler for Intent.ACTION_OPEN_DOCUMENT
 * Read more about ActivityResult here: https://developer.android.com/training/basics/intents/result
 */
val actionOpenTextFile = registerForActivityResult(OpenDocument()) { uri ->
    if(uri != null) {
        // textPath is an instance of java.nio.file.Path
        val textPath = AndroidPaths.get(documentUri)
    }
}

actionOpenTextFile.launch(arrayOf("text/*"))

Get a Path from a document Uri

You can get a Path from a document Uri by using the method AndroidPaths.get:

/**
 * documentUri refers to a Uri your app has received using SAF
 */
val path = AndroidPaths.get(documentUri)

Get file size

You can get the file size by using the method Files.size:

val path = AndroidPaths.get(documentUri)
val size = Files.size(path)

Get InputStream

You can get an InputStream of by using the method Files.newInputStream:

val path = AndroidPaths.get(documentUri)
val inputStream = Files.newInputStream(path)

Read a text file

You can read a text file by using the method Files.readAllLines:

/**
 * documentUri refers to a Uri your app has received using SAF
 */
val path = AndroidPaths.get(documentUri)
val content = Files.readAllLines(path).joinToString(separator = "\n")

Get a bitmap from an image

Modifying a file requires to scan it to make MediaStore aware of the file changes (size, modification date, etc.). To request a scan for a media URI, use the scanUri method:

val path = AndroidPaths.get(documentUri)
val inputStream = Files.newInputStream(path)
val bitmap = BitmapFactory.decodeStream(inputStream)