java.io.File compatible SAF library

Overview

DocumentFileX

java.io.File compatible SAF implementation

Tired of SAF bullshits? Implement SAF with ease!

This library is in alpha stage. Most features are working, but some features might not work as intended.

Features

  • Interoperable with java.io.File with some exceptions
  • File.getName() without overhead
  • Faster Directory IO
  • Get child FileX without overhead
  • Slightly improved listFiles() //√evil
  • Automatic URI type detection
  • File metadata caching
  • Useful URI extensions
  • (WIP) kotlin-stdlib File extension compatible extension methods

Setup

dependencies {
    implementation 'xyz.quaver:documentfilex:0.7.1'
}

Sample Code

File I/O

⚠️ You have to use File I/O methods declared in xyz.quaver.io.util.*
Default kotlin extension methods do not work with SAFileX Instances.

)) ">
val file = FileX(context, uri)

file.writeText("Hello, SAF! You're dumb.")
val text = file.readText() // "Hello, SAF! You're dumb."

val data = listOf(0x82, 0x72, 0x82, 0x60, 0x82, 0x65, 0x82, 0xA4, 0x82, 0xF1, 0x82, 0xBF).map {
    it.toByte()
}.toByteArray()

file.writeBytes(data)
val text = file.readText(data, Charset.forName(<small quiz for you>))

Directory I/O

Directory I/O is supported by tree://... URI

// Returns FileX sichouson.list().forEach { // Returns Uri string .... } } ">
val folder = FileX(context, uri, "akita") // No overhead
val child = folder.getChild("daisen") // No overhead
val neighbor = FileX(context, folder.parent, "yamagata") // No overhead
val neice = folder.getNeighbor("iwate/morioka/nakano.txt") // No overhead

if (neice.parent.mkdirs()) {
    neice.createNewFile()
    neice.renameTo(FileX(context, neice.parent, "kurokawa.json"))
}

folder.listFiles().forEach { sichouson -> // Returns FileX
    sichouson.list().forEach { // Returns Uri string
        ....
    }
}

Caching

Cache is only available for the Documents URI and Tree URI

Enabling the Cache

With constructor:

FileX(..., cached=true)

With an instance: You can call invalidate() anytime you want to update Cache even when cached is false. However, cached data will only be used by the FileX instance when the property cached is true. Alternatively you can directly access the cache with FileX.cache

file.cached = true
file.invalidate()

You can update the cache with FileX.invalidate() or Cache.invalidate

Caching might impact the performance when large amounts of instances are created. Enable cache when both of these criteria are met:

  • Frequent Access to the File properties
  • Not a lot of instances are crated at the same time

Also note that the cache of the instances created by listFiles() are disabled to improve performance.

You might also like...
Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platform the code is running.

Trail Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platfor

Multiplaform kotlin library for calculating text differences. Based on java-diff-utils, supports JVM, JS and native targets.

kotlin-multiplatform-diff This is a port of java-diff-utils to kotlin with multiplatform support. All credit for the implementation goes to original a

A low intrusive, configurable android library that converts layout XML files into Java code to improve performance

qxml English 一个低侵入,可配置的 Android 库,用于将 layout xml 文件转换为 Java 代码以提高性能。 与X2C的对比 X2C: 使用注解处理器生成View类,使用时需要在类中添加注解,并替换setContentView方法,侵入性较强; 对于布局属性的支持不够完美

Java implementation of a Disk-based LRU cache which specifically targets Android compatibility.

Disk LRU Cache A cache that uses a bounded amount of space on a filesystem. Each cache entry has a string key and a fixed number of values. Each key m

a simple cache for android and java

ASimpleCache ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。 1、它可以缓存什么东西? 普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 b

Runtime code generation for the Java virtual machine.
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

gRPC and protocol buffers for Android, Kotlin, and Java.

Wire “A man got to have a code!” - Omar Little See the project website for documentation and APIs. As our teams and programs grow, the variety and vol

Apk parser for java

APK parser lib, for decoding binary XML files, getting APK meta info. Table of Contents Features Get APK-parser Usage 1. APK Info 2. Get Binary XML an

Apk parser for java

APK parser lib, for decoding binary XML files, getting APK meta info. Table of Contents Features Get APK-parser Usage 1. APK Info 2. Get Binary XML an

Comments
  • Fix a few issues with getVolumePath

    Fix a few issues with getVolumePath

    Fix a few issues with getVolumePath

    • Not working on API30 => use getDirectory instead of getPath / getPathFile
    • GetUuid not available on API19-20 => raise minSDK to API21
    bug good first issue 
    opened by RobbWatershed 9
  • [Question] Efficiency of Runtime.addShutdownHook

    [Question] Efficiency of Runtime.addShutdownHook

    I've seen you're using Runtime.addShutdownHook to schedule cache cleanup in https://github.com/tom5079/DocumentFileX/blob/4835cda39a14e74f90c9a0805c676b24e10b5139/library/src/main/java/xyz/quaver/io/util/DeleteOnExitHook.kt#L60

    I'd like to know your feedback about the efficiency of this (i.e. has it been tested successfuly on various real-world devices ?), as the documentation of this method mostly describes what happens around the Java VM, and is not clear at all about what it means for an Android app.

    Alternatively, have you considered giving users the possibility of calling the hook from their app ?

    bug good first issue question 
    opened by RobbWatershed 4
  • [Question] Choice of ContentResolver.openOutputStream default mode

    [Question] Choice of ContentResolver.openOutputStream default mode

    I've noticed you're using "w" as the default mode for ContentResolver.openOutputStream, which I've been doing myself until the moment when :

    • I opened an existing file of, say 100 bytes...
    • ...to update it with a new content of 91 bytes...
    • ...and realized afterwards that the updated files contains 91 bytes of the new content + 9 bytes of the old content

    The file was a JSON file... and it was FUBAR after that.

    I then switched to "wt" (write-truncate) to make it more intuitive, as the most frequent use-case is updating an entire file, not selectively updating a chunk of it.

    Wouldn't it be better if you did the same here ?

    https://github.com/tom5079/DocumentFileX/blob/2a916db0a67406df9cf7755153ae0f02e8735ac0/library/src/main/java/xyz/quaver/io/util/SAFileXReadWrite.kt#L36

    https://github.com/tom5079/DocumentFileX/blob/bc10ba3f63a3a5918005e507f23a91ce6486b9c5/library/src/main/java/xyz/quaver/io/util/DocumentUtil.kt#L272

    enhancement good first issue question 
    opened by RobbWatershed 1
  • [Question] Unit tests ?

    [Question] Unit tests ?

    I'd like to contribute a few additions but, as there's no documentation and no design documents, I'm kinda afraid to break things without realizing it.

    I guess you're testing new changes through your app, which is totally fine as far as you're concerned, but imo not enough for a library aimed at being reusable outside of that app.

    => Is there a way we could set up unit tests to detect any regression and somehow show how the API works ?

    I'm not sure how to start, but I would definitely help enrich the first tests if you got a few of them running...

    documentation enhancement help wanted good first issue 
    opened by RobbWatershed 10
Owner
null
A lightning fast, transactional, file-based FIFO for Android and Java.

Tape by Square, Inc. Tape is a collection of queue-related classes for Android and Java. QueueFile is a lightning-fast, transactional, file-based FIFO

Square 2.4k Dec 30, 2022
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.5k Dec 9, 2022
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.4k Dec 29, 2022
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.5k Dec 9, 2022
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.4k Dec 29, 2022
Map strings from csv to xml file

CsvToXmlMapper While translating your app, your translator provides you with a .csv file containing the translated strings and you wonder how boring a

Abhriya Roy 6 Sep 25, 2021
Scoper - Access any file with zero permission required

Scoper - Access any file with zero permission required With this codebase you will able to access file from your mobile without requiring permission o

Fakhrul Alam Siddiqei 5 Oct 4, 2022
Scanning APK file for URIs, endpoints & secrets.

APKLeaks Scanning APK file for URIs, endpoints & secrets. Installation from Pypi from Source from Docker Usage Options Output Pattern Pattern Argument

Dwi Siswanto 3.5k Jan 9, 2023
UPnP/DLNA library for Java and Android

Cling EOL: This project is no longer actively maintained, code may be outdated. If you are interested in maintaining and developing this project, comm

4th Line 1.6k Jan 4, 2023
Error handling library for Android and Java

ErrorHandler Error handling library for Android and Java Encapsulate error handling logic into objects that adhere to configurable defaults. Then pass

null 237 Dec 29, 2022