Android File Write Permissions and Path Selection: A Practical Guide to Resolving EROFS Errors

Dec 08, 2025 · Programming · 13 views · 7.8

Keywords: Android File Writing | EROFS Error | Storage Permission Management

Abstract: This article provides an in-depth exploration of the common EROFS (Read-only file system) error in Android development, analyzing its root cause as applications attempting to write to root directories without proper permissions. By comparing the access mechanisms of internal and external storage, it details how to correctly use getFilesDir() and getExternalFilesDir() methods to obtain writable paths. The article also discusses best practices for permission management, including proper usage scenarios for WRITE_EXTERNAL_STORAGE permission, and presents alternatives for avoiding serialization of large data, such as using static data members for temporary storage. Finally, it clarifies common misconceptions about SD card slots, emphasizing the characteristics of external storage in modern Android devices.

Root Cause Analysis of EROFS Error

In Android development, when attempting to create files using FileOutputStream, developers often encounter FileNotFoundException accompanied by EROFS (Read-only file system) error messages. The core issue lies in applications trying to write to directories without write permissions. Specifically, paths like /2ozjfFQzwv in error messages indicate the program is attempting to write to the root directory of internal storage, which Android system restricts for security reasons.

Correct File Path Selection Strategy

Android provides two main writable storage areas: internal storage and external storage. Internal storage is private to the application and accessible without additional permissions; external storage may require WRITE_EXTERNAL_STORAGE permission, depending on Android version and storage location.

To properly create files, appropriate file paths must be obtained first. Here are two recommended approaches:

// Method 1: Using internal storage directory
File internalFile = new File(getFilesDir(), "filename.txt");
FileOutputStream internalStream = new FileOutputStream(internalFile);

// Method 2: Using application-private directory in external storage
File externalFile = new File(getExternalFilesDir(null), "filename.txt");
// On Android 6.0 and above, dynamic request for WRITE_EXTERNAL_STORAGE permission may be needed
FileOutputStream externalStream = new FileOutputStream(externalFile);

getFilesDir() returns the application's private directory in internal storage, which requires no special permissions for read/write operations. getExternalFilesDir() returns the application's private directory in external storage; since Android 4.4, applications can access their own external private directories without permissions.

Important Considerations for Permission Management

Several key concepts need clarification regarding permission management:

  1. There is no WRITE_INTERNAL_STORAGE permission in Android. Access to internal storage is automatically managed by the system, with applications only able to access their own private directories.
  2. The WRITE_EXTERNAL_STORAGE permission is primarily for accessing public areas of external storage, such as DCIM, Downloads directories. For an application's own external private directory (obtained via getExternalFilesDir()), this permission is typically not required since Android 4.4.
  3. In Android 6.0 (API level 23) and above, dangerous permissions (including WRITE_EXTERNAL_STORAGE) must be requested dynamically at runtime.

Alternative Solutions for Large Data Transfer

When transferring large data (such as images) between Activities, direct serialization may be impractical. Besides writing to files and reading them back, consider these alternatives:

// Using static data members for temporary storage
public class DataHolder {
    private static Bitmap sharedImage;
    
    public static void setImage(Bitmap image) {
        sharedImage = image;
    }
    
    public static Bitmap getImage() {
        return sharedImage;
    }
}

// In sending Activity
DataHolder.setImage(largeBitmap);

// In receiving Activity
Bitmap receivedImage = DataHolder.getImage();

This approach avoids file I/O operations but requires attention to memory management and lifecycle issues. Static data members remain in memory until the application process ends, making them unsuitable for storing large amounts of data or data requiring long-term preservation.

Modern Understanding of External Storage

An important clarification about external storage is that in modern Android devices, "external storage" typically refers to built-in shared storage space, not physical SD cards. Since mid-2010, most Android devices have included external storage as part of onboard flash memory rather than removable media. This means:

This design ensures consistent application experience across different devices while maintaining appropriate security boundaries.

Best Practices Summary

Based on the above analysis, we summarize the following best practices:

  1. Always use File objects with appropriate directory paths when creating FileOutputStream
  2. Prioritize internal storage (getFilesDir()) for private data storage, requiring no permissions
  3. Use application-private directories in external storage (getExternalFilesDir()) for shared or larger files
  4. Properly handle permission requests, especially runtime permissions for Android 6.0+
  5. For temporary large data transfer, consider memory-based solutions like static data members
  6. Understand modern Android storage architecture to avoid over-reliance on physical SD cards

By following these principles, developers can avoid EROFS errors while ensuring application compatibility and security across different Android devices and versions.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.