Android storage area space

Android Storage areas include Internal Storage and External Storage.

1 Internal Storage

Internal storage partition: physical locations include /data, /System, and /cache directories in the root directory of the Android System.

  • Root’s mobile phone can view internal files through file management software.
  • Normal mobile phones we can use AndroidStudioDevice File ExplorerTools to view internal storage under the file.

Internal storage partition features:

  1. Internal partitions are always available.
  2. It stores App private files and cannot be accessed by other apps.
  3. After the App is uninstalled, the App data stored in the internal partition will be deleted.
  4. No additional permission is required.

1.1 /system Directory:

/system

The system store directory, which is the same level as /sdcard and /data, is a level 1 subdirectory of the root directory.

Access: It can be accessed through the getRootDirectory method of the Environment class

private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; Private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system"); // If the environment variable is specified, use the specified value, otherwise use "/system" public static @nonnull File getRootDirectory() {return DIR_ANDROID_ROOT; }Copy the code

It corresponds to subdirectories:

  • /system/app: Stores the software attached to the ROM itself, that is, system software.
  • /system/data: Stores data files of core system software in /system/ APP.
  • /system/priv-app: ApK files for system level applications customized by mobile phone manufacturers.
  • /system/bin: Stores the local programs of the system, which are mainly components of the Linux system.
  • /system/media: Store some sound effects, ring tones, switch motor pictures, etc.

1.2 /data directory:

/data

Data directory, the top level directory for our App’s private data store.

Access: by the Environment. GetDataDirectory visit () method

    private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
    /**
     * Return the user data directory.
     */
    public static File getDataDirectory() {
        return DIR_ANDROID_DATA;
    }
Copy the code

1.2.1 Application Private Directories

/ data/data / < app package name >

Access: This can be obtained through the getDataDir() method of the Context object. During development, we should not use this directory directly, but should use file, cache, etc., which are already defined by the system

ContextImpl:

@Override public File getDataDir() { if (mPackageInfo ! = null) { File res = null; if (isCredentialProtectedStorage()) { res = mPackageInfo.getCredentialProtectedDataDirFile(); } else if (isDeviceProtectedStorage()) { res = mPackageInfo.getDeviceProtectedDataDirFile(); } else { res = mPackageInfo.getDataDirFile(); //mPackageInfo is the object of LoadedApk. }... } else { throw new RuntimeException( "No package details found for package " + getPackageName()); }}Copy the code

It corresponds to subdirectories:

  • / data/data / < app package name > / files: Directory of files stored inside the App.
  • / data/data / < app package name > / cache: Cache directory stored inside the App.
  • / data/data / < app package name > / databases: Database directory stored inside the App.
  • / data/data / < app package name > / shared_prefs: SP directory stored inside the App.
  • / data/data / < app package name > / lib: Lib directory stored inside the App.

1.2.2 Application Files Directory

/ data/data / < app package name > / files

Files directory is the directory of files stored inside our App.

Access: The file directory of the application private directory can be obtained using the getFilesDir() method of the Context object.

The root address of the openFileOutput() method of the Context object is the files directory.

ContextImpl source code:

    @Override
    public File getFilesDir() {
        synchronized (mSync) {
            if (mFilesDir == null) {
                mFilesDir = new File(getDataDir(), "files");
            }
            return ensurePrivateDirExists(mFilesDir);
        }
    }

Copy the code

1.2.3 Application Cache Directory

/ data/data / < app package name > / cache

Cache directory is the cache directory stored inside our App.

Access: The cache directory can be obtained using the getCacheDir() method of the Context object.

ContextImpl source code:

    @Override
    public File getCacheDir() {
        synchronized (mSync) {
            if (mCacheDir == null) {
                mCacheDir = new File(getDataDir(), "cache");
            }
            return ensurePrivateCacheDirExists(mCacheDir, XATTR_INODE_CACHE);
        }
    }
Copy the code

If you want to hold some data temporarily rather than permanently, you should use a special cache directory to hold the data. Instead of relying on the system to clean up these files for you, you should always maintain the cache files yourself, keeping them within a reasonable limit (such as 1MB). These files are removed when the user uninstalls your application

Note the following features of cache files:

  1. The system automatically deletes files in this directory when the disk space is insufficient.
  2. The system will always delete old files first.
  3. We can use the StorageManager class related methods to better manage our delete rules.
  4. App can account for the size of the cache space StorageManager. GetCacheQuotaBytes (Java. Util. UUID).
  5. The cache space that exceeds the quota allocated by App will be deleted first. We should try our best to keep the files in our cache space below the quota value, which will reduce the probability of deleting our cache files as much as possible.

1.2.4 Application Databases directory

/ data/data / < app package name > / databases

The Databases directory holds the application’s database files.

Access: The Databases directory can be obtained using the getDatabasesDir() method of the Context object.

ContextImpl source code:

private File getDatabasesDir() { synchronized (mSync) { if (mDatabasesDir == null) { if ("android".equals(getPackageName())) { mDatabasesDir = new File("/data/system"); } else { mDatabasesDir = new File(getDataDir(), "databases"); } } return ensurePrivateDirExists(mDatabasesDir); }}Copy the code

This method is a private method and cannot be accessed directly; we usually use DB’s related encapsulation method to access it. The database directory is “/data/system”. The database directory is “/data/ data/<app package name >/databases “.

1.2.5 Application shared_prefs directory

/ data/data / < app package name > / shared_prefs

If an application wants to store key-value pair information with a small amount of data, you can use SharedPreferences to store the data, for example, application-related configuration information.

Access is done through the getSharedPreferences method of the Context object.

Access: This can be obtained using the getPreferencesDir() method, which we cannot use directly.

ContextImpl source code:

private File getPreferencesDir() { synchronized (mSync) { if (mPreferencesDir == null) { mPreferencesDir = new File(getDataDir(), "shared_prefs"); } return ensurePrivateDirExists(mPreferencesDir); }}Copy the code

1.3 / Cache Directory:

/cache

Download the cache contents directory, which is the same as /system and /data

Access: you can access through the Environment getDownloadCacheDirectory method

    private static final File DIR_DOWNLOAD_CACHE = getDirectory(ENV_DOWNLOAD_CACHE, "/cache");
    public static File getDownloadCacheDirectory() {
        return DIR_DOWNLOAD_CACHE;
    }
Copy the code

2 External Storage

Many people always think of external storage as an external SD card, which is a misconception. The external storage can be an external SD card or a partial partition of the internal memory card.

External storage can be divided into public directories and private directories. The root directory sdcard/ is a public directory. Sdcard /Android/data/< package name >/ belongs to the private directory.

External storage partition features:

  1. External partitions are not always available.
  2. Files saved here may be accessed by other programs.
  3. When users to uninstall the app, the system will only delete the external cache directory (Context) getExternalCacheDir ()) and the file directory (Context) getExternalFilesDir ()) of the relevant documents.
  4. In some cases, the WRITE_EXTERNAL_STORAGE or READ_EXTERNAL_STORAGE permission needs to be applied.

Google has been limiting the use of external storage in the new version of the app. We’ll elaborate on private and public directories below.

2.1 External Public Storage Directories

External public storage directories have the following features:

  • Can be accessed by other applications
  • Resources can be retained after the app is uninstalled
  • Permissions?

Restricted by the latest version of AndroidR(11), it is forbidden to read and write in the SD card public directory, except for media resources.

In the early days, in order to find some files of the APP conveniently, many developers created a resource file in the root directory to store the program in multiple directories. This is fine for one APP, but once all apps are developed this way, Android users will open Explorer and find folders full of files on their SD cards.

AndroidQ(10) starts performing partitioned storage. Simply put, the application can read and write files only in the sandbox environment, that is, in its own application directory. Other media files can be accessed through MediaStore. (Google still has one hand reserved for developers. In the applications of targetSdkVersion = 29, set the android: requestLegacyExternalStorage = “true”, can not boot partition storage, file read before normal use.

AndroidR(11) starts to enforce partition storage. And on all Android11 devices, even if targetSdkVersion<30, the SD card root directory is not allowed to read and write. Therefore, you need to save your own files in the external private storage directory, and save photos and videos to the public storage directory of system media files.

2.1.1 External SD Card root Directory

/storage/emulated/0

The sd card root for external storage, which is the top level directory we normally see from the file manager

Access mode: YesEnvironmentOf the classgetExternalStorageDirectoryMethod access:

    @Deprecated
    public static File getExternalStorageDirectory() {
        throwIfUserRequired();
        return sCurrentUser.getExternalDirs()[0];
    }
Copy the code

AndroidQ(10) used to be able to customize some directories based on the root directory, which is currently prohibited and not discussed.

2.1.2 External Public Special Directories

/storage/emulated/0/DCIM

/storage/emulated/0/Music

/storage/emulated/0/Movies

/storage/emulated/0/Pictures

/storage/emulated/0/Downloads

AndroidQ (10) in the past, through the Environment getExternalStoragePublicDirectory method can access public directory. This method has several specific parameter types (the parameter cannot be null) :

     *            {@link #DIRECTORY_MUSIC}, 
     *            {@link #DIRECTORY_PODCASTS},
     *            {@link #DIRECTORY_RINGTONES}, 
     *            {@link #DIRECTORY_ALARMS},
     *            {@link #DIRECTORY_NOTIFICATIONS}, 
     *            {@link #DIRECTORY_PICTURES},
     *            {@link #DIRECTORY_MOVIES}, 
     *            {@link #DIRECTORY_DOWNLOADS},
     *            {@link #DIRECTORY_DCIM}, or 
     *            {@link #DIRECTORY_DOCUMENTS}

Copy the code

In AndroidQ (10), this interface is deprecated. Alternative to suggest using Context. GetExternalFilesDir, MediaStore, Intent. ACTION_OPEN_DOCUMENT.

AndroidQ(10) introduced a new definition of media file sharing collection. If you want to access media shared files outside the sandbox, such as photos, music, videos, etc., You need to apply for new media permissions :READ_MEDIA_IMAGES,READ_MEDIA_VIDEO, and READ_MEDIA_AUDIO. The application method is the same as the original storage permission.

2.2 External Private Storage Directories

Due to the limited internal storage space, Android provides a special directory in the external storage space for apps to store private files.

External private storage directories have the following features:

  • Cannot be accessed by other applications
  • Resources cannot be retained after the app is uninstalled
  • Permissions?

2.2.1 External Private Storage Root Directory

/ storage/emulated / 0 / Android/data / < app package name >

2.2.2 External Private Storage Files Directory

/ storage/emulated / 0 / Android/data / < app package name > / files

Usually put some data that has been stored for a long time.

Access: The getExternalFilesDir() method

ContextImpl source code:

@Override public File getExternalFilesDir(String type) { // Operates on primary external storage final File[] dirs = getExternalFilesDirs(type); return (dirs ! = null && dirs.length > 0) ? dirs[0] : null; } @Override public File[] getExternalFilesDirs(String type) { synchronized (mSync) { File[] dirs = Environment.buildExternalStorageAppFilesDirs(getPackageName()); if (type ! = null) { dirs = Environment.buildPaths(dirs, type); } return ensureExternalDirsExistOrFilter(dirs); }}Copy the code

Parameter to the getExternalFilesDir method that represents a subdirectory in the /files directory to be created. Through the source code, we see it call Environment. BuildExternalStorageAppFilesDirs (getPackageName ()) to obtain/files directory.

BuildExternalStorageAppFilesDirs according to the number of external storage, returns an array of File;

GetExternalFilesDir just takes the first one, which is the main external storage directory.

Environment. BuildExternalStorageAppFilesDirs method:

    public static final String DIR_ANDROID = "Android";
    private static final String DIR_DATA = "data";
    private static final String DIR_MEDIA = "media";
    private static final String DIR_OBB = "obb";
    private static final String DIR_FILES = "files";
    private static final String DIR_CACHE = "cache";
    
    @UnsupportedAppUsage
    public static File[] buildExternalStorageAppFilesDirs(String packageName) {
        throwIfUserRequired();
        return sCurrentUser.buildExternalStorageAppFilesDirs(packageName);
    }
Copy the code

Calls to the Environment the inner class UserEnvironment buildExternalStorageAppFilesDirs method:

   public File[] buildExternalStorageAppFilesDirs(String packageName) {
       return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
   }
Copy the code

Directories Android, Data, packageName, and Files are created according to the parent directory relationship.

2.2.3 External Private Storage Cache Directory

/ storage/emulated / 0 / Android/data / < app package name > / cache

Generally used to store temporary cached data.

Access: The getExternalCacheDir() method

ContextImpl source code:

    @Override
    public File getExternalCacheDir() {
        // Operates on primary external storage
        final File[] dirs = getExternalCacheDirs();
        return (dirs != null && dirs.length > 0) ? dirs[0] : null;
    }

    @Override
    public File[] getExternalCacheDirs() {
        synchronized (mSync) {
            File[] dirs = Environment.buildExternalStorageAppCacheDirs(getPackageName());
            return ensureExternalDirsExistOrFilter(dirs);
        }
    }

Copy the code

Logic is similar to files directory, and ultimately UserEnvironment buildExternalStorageAppCacheDirs method calls to the Environment inner class.

    public File[] buildExternalStorageAppCacheDirs(String packageName) {
        return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
    }

Copy the code