npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

expo-filesystem-android-external-storage

v1.0.3

Published

Expo native module for raw file system access on Android external storage

Readme

expo-filesystem-android-external-storage

An Expo Config Plugin and Native Module for accessing Android's External Storage (e.g. /sdcard/Documents/) directly using java.io.File, bypassing Expo FileSystem's scoped storage restrictions.

Why this package?

We built this because we faced significant limitations with standard approaches when developing TidGi-Mobile (a TiddlyWiki app that needs to sync with desktop):

  1. SAF (Storage Access Framework) is too slow: We need to sync thousands of small .tid files. Using DocumentFile and SAF APIs for batch operations was incredibly slow compared to direct file access.
  2. expo-file-system is restricted: Even if you add MANAGE_EXTERNAL_STORAGE permission to your app.json, the standard expo-file-system APIs are scoped to the app's internal directory (or specific cache dirs). They generally cannot access arbitrary paths like /sdcard/Documents/TidGi/ directly.
  3. Permissions alone are insufficient: Simply adding the permissions below to app.json does not grant expo-file-system access to external storage due to its internal "scoped" design.
    "permissions": [
      "android.permission.READ_EXTERNAL_STORAGE",
      "android.permission.WRITE_EXTERNAL_STORAGE",
      "android.permission.MANAGE_EXTERNAL_STORAGE"
    ]
  4. Legacy API failures: We tried using expo-file-system's legacy storage flags, but they often failed or were inconsistent across Android versions.

Therefore, we implemented this Native Module which uses standard java.io.File APIs in Kotlin. This requires:

  • Expo Development Client: You cannot use Expo Go because this package contains custom native code. You must build a custom dev client or a production build (prebuild).
  • MANAGE_EXTERNAL_STORAGE Permission: The user must grant "All files access" in system settings.

Features

  • Direct File Access: Read and write to any path the app has permission for.
  • Bypass Scoped Storage: Works with absolute paths (e.g. /storage/emulated/0/...).
  • Standard Operations: exists, read, write, mkdir, list (recursive), delete.
  • Permission Helper: Check for MANAGE_EXTERNAL_STORAGE status.

Installation

npm install expo-filesystem-android-external-storage
# or
pnpm add expo-filesystem-android-external-storage

Configuration

Android Manifest

This module requires the MANAGE_EXTERNAL_STORAGE permission to be effective for broad access.

Add this to your app.json / app.config.ts if you want Expo to add the permission to AndroidManifest.xml (though you might need a custom config plugin to add R.attr.requestLegacyExternalStorage or similar attributes if targeting Android 10).

Actually, this package is primarily the native implementation. You should ensure your app requests the permission at runtime (e.g. using Intent to open Settings).

Usage

import { ExternalStorage } from 'expo-filesystem-android-external-storage';

async function example() {
  const path = '/sdcard/Documents/myfile.txt';

  // Check existence
  if (await ExternalStorage.exists(path)) {
    console.log('File exists');
    const content = await ExternalStorage.readFileUtf8(path);
  } else {
    // Write file
    await ExternalStorage.writeFileUtf8(path, 'Hello World');
  }

  // List directory
  const files = await ExternalStorage.readDir('/sdcard/Documents');
  console.log('Files:', files);
}

Expo Config Plugin

This package includes a config plugin to automatically add the MANAGE_EXTERNAL_STORAGE permission to your AndroidManifest.xml.

In app.json or app.config.ts:

{
  "expo": {
    "plugins": [
      "expo-filesystem-android-external-storage"
    ]
  }
}

API

exists(path: string): Promise<boolean>

Checks if a file or directory exists.

getInfo(path: string): Promise<FileInfo>

Gets metadata (size, modification time, isDirectory).

readFileUtf8(path: string): Promise<string>

Reads a file as a UTF-8 string.

writeFileUtf8(path: string, content: string): Promise<void>

Writes a UTF-8 string to a file. Creates parent directories if needed.

readDir(path: string): Promise<string[]>

Lists files in a directory (non-recursive).

readDirRecursive(path: string): Promise<string[]>

Recursively lists all files, returning paths relative to the root. Skips .git, node_modules, etc.

mkdir(path: string): Promise<void>

Creates a directory and necessary parent directories.

deleteFile(path: string): Promise<void>

Deletes a file.

rmdir(path: string): Promise<void>

Deletes a directory recursively.

isExternalStorageManager(): Promise<boolean>

Checks if the MANAGE_EXTERNAL_STORAGE permission is granted (Android 11+).

License

MIT