ModernStorage is a group of libraries that provide an abstraction layer over storage on Android to simplify its interactions

Overview

ModernStorage

ModernStorage

ModernStorage is a group of libraries that provide an abstraction layer over storage on Android to simplify its interactions by apps developers. ModernStorage is:

  • Easy to use: ModernStorage focuses on API simplicity. Rather than calling four separate methods with the Android Framework API, you only need to call one.
  • Opinionated: ModernStorage is written by the Android DevRel team in collaboration with the Android Storage team, taking in account all the feedback from the developer community to address common issues when dealing with storage on Android.

Download

ModernStorage is available on mavenCentral().

// For MediaStore interactions
implementation("com.google.modernstorage:modernstorage-mediastore:1.0.0-alpha02")

// For Storage Access Framework interactions on API 26+
implementation("com.google.modernstorage:modernstorage-filesystem:1.0.0-alpha02")

Quick Start

  • For MediaStore interactions, check out the sample app
  • For non-media files on shared storage & SAF interactions, stay tuned for the upcoming filesystem package

Contributions

We're still at an early stage sharing the vision of ModernStorage and would love to have more feature requests and ideas proposed as issues. We would be glad to review pull requests, but keep in mind that we want to minimize expanding the API surface until we get more feedback from developers. Make sure to read the Contributing page first though.

License

Copyright 2021 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Issues
  • Request: add easy way to prepare a DocumentFile by file-path

    Request: add easy way to prepare a DocumentFile by file-path

    Because Google said that the current API (of DocumentFile.fromFile) doesn't provide it, and that it doesn't plan on adding such a thing either: https://issuetracker.google.com/issues/179478996#comment11

    My request was that given a file-path, I should be able to reach it via DocumentFile (assuming I have access to the file, and that indeed it's a file on the device file system), and perform all operations on it like any other DocumentFile instance.

    opened by AndroidDeveloperLB 8
  • Add basic github action to test build

    Add basic github action to test build

    It adds basic GitHub Actions to test build only now.

    opened by utzcoz 7
  • Introducing Kotlin linter checks in github actions

    Introducing Kotlin linter checks in github actions

    Adding Ktlint linter for kotlin as a static GitHub check will reduce the code review period and improve code style

    Found the following errors when checked with Ktlint 0.37.1^v

    /home/farees/opensource/modernstorage/media/src/androidTest/java/com/google/modernstorage/media/ExampleInstrumentedTest.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/CustomActivityResultContracts.kt:39:1: Needless blank line(s)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaCollection.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaCollection.kt:34:16: Missing spacing after "when"
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaCollection.kt:41:16: Missing spacing after "when"
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaCollection.kt:47:1: Needless blank line(s)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaCollection.kt:59:16: Missing spacing after "when"
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaCollection.kt:66:16: Missing spacing after "when"
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaQuery.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaResource.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaStoreClient.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/MediaStoreClient.kt:19:1: Imports must be ordered in lexicographic order without any empty lines in-between
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/Permission.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/StorageLocation.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/media/src/main/java/com/google/modernstorage/media/StorageLocation.kt:23:1: Missing space after //
    /home/farees/opensource/modernstorage/media/src/test/java/com/google/modernstorage/media/ExampleUnitTest.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/sample/src/androidTest/java/com/google/modernstorage/sample/ExampleInstrumentedTest.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/MainActivity.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/MainActivity.kt:42:1: Unexpected indentation (16) (should be 12)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/MediaStoreFragment.kt:155:11: Missing spacing after "if"
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/MediaStoreFragment.kt:161:1: Unexpected blank line(s) before "}"
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/MediaStoreViewModel.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/MediaStoreViewModel.kt:58:15: Missing spacing after "if"
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:1:1: File must end with a newline (\n)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:21:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:22:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:23:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:24:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:28:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:29:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:30:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/main/java/com/google/modernstorage/sample/mediastore/SampleData.kt:31:1: Exceeded max line length (100) (cannot be auto-corrected)
    /home/farees/opensource/modernstorage/sample/src/test/java/com/google/modernstorage/sample/ExampleUnitTest.kt:1:1: File must end with a newline (\n)
    
    
    opened by FareesHussain 5
  • Introduce result type

    Introduce result type

    • [x] ~~Upgrade ModernStorage to 1.5.10~~ Keep using Kotlin 1.4.32 due to compiler bug
    • [x] Rename MediaStoreClient.kt to MediaStoreRepository.kt
    • [x] Add permission handlers to MediaStoreRepository
    • [x] Rename MediaResource to FileResource
    • [x] Add @Parcelize to FileResource
    • [x] Expand media support to audio files
    • [x] Simplify API naming
    • [x] Add file scanning feature
    • [x] Update sample app
    • [x] Add guide
    • [x] Upgrade project version
    • [x] Add docs publishing action
    opened by yrezgui 4
  • Fix #7: Added Ktlint with spotless

    Fix #7: Added Ktlint with spotless

    Fixes #7

    Will add GitHub checks once https://github.com/google/modernstorage/pull/9 is merged or current changes are approved

    opened by FareesHussain 3
  • Update README with correct maven coordinates

    Update README with correct maven coordinates

    Confirmed the correct coordinates here: https://repo1.maven.org/maven2/com/google/modernstorage/modernstorage-mediastore/maven-metadata.xml.

    opened by saket 2
  • Add two functions that receive a lambda

    Add two functions that receive a lambda

    Description

    In many cases, we may use getResourceByUri() like this:

    mediaStore.getResourceByUri(uri)?.let {
       // .. //
    }
    
    val mediaResource = mediaStore.getResourceByUri(uri)
    if (mediaResource != null) {
      // .. //
     }
    

    I think it could be a little bit more convenient with new functions instead of using scope functions every time.

    What's the difference?

    Added two functions that receive a lambda that has a MediaResource as a receiver.

    • withResourceByUri(uri: Uri, block: (MediaResource?) -> Unit)
    • withResourceByUriIfExist(uri: Uri, block: (MediaResource) -> Unit)

    Before

    mediaStore.getResourceByUri(uri)?.let {
        savedStateHandle.set("currentMediaUri", uri)
        _currentMedia.value = it
    }
    

    After

    mediaStore.withResourceByUri(uri) {
        savedStateHandle.set("currentMediaUri", uri)
        _currentMedia.value = it
    }
    

    I think the function names are not the best choices. So If have any better ideas, hope to give me feedback. Thank you! 😃

    opened by skydoves 1
  • Add filesystem writing example

    Add filesystem writing example

    • [x] Add filesystem writing example
    • [x] Add java.nio writing code snippets in guide
    • [x] Blocked by the inability to access WritableChannel (see crash bug details below)
    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.google.modernstorage.sample, PID: 24988
        java.nio.channels.NonWritableChannelException
            at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:239)
            at java.nio.channels.Channels.writeFullyImpl(Channels.java:79)
            at java.nio.channels.Channels.writeFully(Channels.java:102)
            at java.nio.channels.Channels.access$000(Channels.java:62)
            at java.nio.channels.Channels$1.write(Channels.java:175)
            at java.nio.file.Files.copy(Files.java:2909)
            at java.nio.file.Files.copy(Files.java:3027)
            at com.google.modernstorage.sample.filesystem.FileSystemViewModel$downloadAndSaveContent$1$1.invokeSuspend(FileSystemViewModel.kt:114)
            at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
            at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
            at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
    
    opened by yrezgui 1
  • Filesystem

    Filesystem

    opened by nic0lette 1
  • Improve project infrastructure

    Improve project infrastructure

    • Add Spotless
    • Remove .idea folder (it was a bad idea...)
    • Add issue template
    • Delete boilerplate tests (promise, I'll write them properly very soon!)
    • Add KDOC
    • Update copyright header
    • Add run configurations to help getting started on the projet quickly
    • Add metalava support
    opened by yrezgui 1
  • Newfs

    Newfs

    This is a large rewrite of the ContentFileSystemProvider code based on DocumentPath. The system currently only supports DocumentsProvider backed content:// Uris, but it should be possible to support others, including MediaStore or app FileProvider content:// style Uris.

    opened by nic0lette 1
  • Warning in Filesystem unit tests when using AGP 7.0.0-beta05

    Warning in Filesystem unit tests when using AGP 7.0.0-beta05

    Describe the bug

    Whenever I run the filesystem unit tests, I get an warning in my logs. It doesn't stop the tests to run and they're still succeeding but this warning shouldn't happen. The bug has been introduced when we updated AGP to 7.0.0-beta05 from 4.2.1 (see commit here).

    Executing tasks: [:filesystem:cleanTestDebugUnitTest, :filesystem:testDebugUnitTest] in project /Users/yrezgui/modernstorage
    
    unable to enhance gradle daemon classloader with idea_rt.jar
    org.gradle.api.InvalidUserCodeException: Querying the mapped value of provider(interface java.util.Set) before task ':filesystem:compileDebugUnitTestKotlin' has completed is not supported
    

    To Reproduce

    Steps to reproduce the behavior:

    1. Open project in Android Studio
    2. Run filesystem unit tests
    3. See warning in logs

    Expected behavior

    Warning shouldn't happen. It's not present when using AGP 4.2.1

    Environment:

    • Android Studio version: Arctic Fox beta 05
    • Target SDK version: API 30
    • ModernStorage version: 1.0.0-alpha02
    Filesystem bug 
    opened by yrezgui 0
  • [Filesystem] Add support for Files.probeContentType

    [Filesystem] Add support for Files.probeContentType

    The method Files.probeContentType doesn't seem to work with ContentPath. See documentation here

    Filesystem enhancement 
    opened by yrezgui 2
  • [filesystem] Make `PlatformContract` methods match `DocumentsContract`

    [filesystem] Make `PlatformContract` methods match `DocumentsContract`

    Instead of various methods which are identical, or almost identical, to the DocumentsContract, make PlatformContract define an interface which matches the Android version (with the exception of using java.net.URI rather than android.net.Uri for testing on non-Android devices)

    Interface or abstract class? Both could have default implementations that would allow defining helper methods.

    Perhaps best would be an interface for DocumentsContract and then a class that uses that interface for defining lower level helper methods that can be used by the filesystem classes without worrying about DocumentsContract at all.

    Filesystem enhancement 
    opened by nic0lette 1
  • Emulate IS_PENDING flag from API 21+

    Emulate IS_PENDING flag from API 21+

    The IS_PENDING flag allows a file to not be visible to others applications until it has been processed like when you're still saving its content (see documentation).

    The flag is only available from API 29+ but could possible be emulated on previous Android versions by following this scenario:

    • Save the file content first in the app cache directory
    • Move the file to the right MediaStore collection folder (see getExternalStoragePublicDirectory)
      • The operation should be quick as the file is already on the same storage volume
    • Scan the file in MediaStore
    MediaStore 
    opened by yrezgui 0
  • [filesystem] Add sample demo

    [filesystem] Add sample demo

    • [x] Read text file
    • [x] Display image file
    • [ ] Create text file
    Filesystem 
    opened by yrezgui 0
  • Adapt API surface for Java users

    Adapt API surface for Java users

    Methods should be annotated with @JvmStatic and fields with @JvmField when needed for Java users

    MediaStore 
    opened by yrezgui 0
  • Verify authority when interacting with MediaStore URIs

    Verify authority when interacting with MediaStore URIs

    Verify authority (MediaStore.AUTHORITY) when interacting with MediaStore APIs that require media URIs else return Result.failure.

    • [ ] MediaStoreRepository.getPathByUri
    • [ ] MediaStoreRepository.addMediaFromStream
    • [ ] MediaStoreRepository.scanUri
    • [x] MediaStoreRepository.getResourceByUri
    • [ ] MediaStoreRepository.scanUri
    • [ ] MediaStoreRepository.scanUri
    • [ ] MediaStoreRepository.scanUri
    MediaStore 
    opened by yrezgui 0
  • Jetpack Compose

    Jetpack Compose

    Hey, is there a plan for jetpack compose compatibility?

    MediaStore enhancement 
    opened by viktorisacenko 2
  • Delete media files

    Delete media files

    Currently, we can only add files and not delete them. This feature request should include deleting media files created by 3rd party apps

    MediaStore 
    opened by yrezgui 0
High level parsing to ensure your input is in the right shape and satisfies all constraints that business logic requires.

Parsix High level parsing to ensure your input is in the right shape and satisfies all constraints that business logic requires. It is highly inspired

null 179 Jul 18, 2021
CacheX - A feasible caching library for Android.

CacheX - A feasible caching library for Android.

Romman Sabbir 23 May 9, 2021
Runtime code generation for the Java virtual machine.

Byte Buddy runtime code generation for the Java virtual machine Byte Buddy is a code generation and manipulation library for creating and modifying Ja

Rafael Winterhalter 4.4k Aug 5, 2021
WebSocket & WAMP in Java for Android and Java 8

Autobahn|Java Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android. Autobahn|Java is a subproject of the A

Crossbar.io 1.4k Jul 28, 2021
WebSocket & WAMP in Java for Android and Java 8

Autobahn|Java Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android. Autobahn|Java is a subproject of the A

Crossbar.io 1.4k Jul 28, 2021
General purpose utilities and hash functions for Android and Java (aka java-common)

Essentials Essentials are a collection of general-purpose classes we found useful in many occasions. Beats standard Java API performance, e.g. LongHas

Markus Junginger 1.3k Jul 26, 2021
General purpose utilities and hash functions for Android and Java (aka java-common)

Essentials Essentials are a collection of general-purpose classes we found useful in many occasions. Beats standard Java API performance, e.g. LongHas

Markus Junginger 1.3k Jul 26, 2021
✔️ Secure, simple key-value storage for Android

Hawk 2.0 Secure, simple key-value storage for android Important Note This version has no backward compatibility with Hawk 1+ versions. If you still wa

Orhan Obut 3.8k Jul 26, 2021
Access and process various types of personal data in Android with a set of easy, uniform, and privacy-friendly APIs.

PrivacyStreams PrivacyStreams is an Android library for easy and privacy-friendly personal data access and processing. It offers a functional programm

null 268 Jul 12, 2021
a SharedPreferences replacement for Android with multiprocess support

DEPRECATED - no longer actively maintained Tray - a SharedPreferences replacement for Android If you have read the documentation of the SharedPreferen

HCI @ gcx 2.3k Jul 19, 2021
Scalable vector graphics for Android

Sharp Sharp is a Scalable Vector Graphics (SVG) implementation for Android. It facilitates loading vector graphics as SharpDrawables, and can effectiv

Pixplicity 982 Jun 21, 2021
A robust native library loader for Android.

ReLinker A robust native library loader for Android. More information can be found in our blog post Min SDK: 9 JavaDoc Overview The Android PackageMan

Keepsafe 2.5k Aug 2, 2021
Predictable state container for JavaScript apps

Redux is a predictable state container for JavaScript apps. (Not to be confused with a WordPress framework – Redux Framework) It helps you write appli

Redux 56.4k Aug 4, 2021
A log collector for Android

Puree Description Puree is a log collector which provides the following features: Filtering: Enable to interrupt process before sending log. You can a

Cookpad 469 Jul 7, 2021