Android 内部存储和外部存储 - chuwuwang/ReadingNote GitHub Wiki

Internal File Storage 应用内部存储

  • 存储永远都是处于可用状态的,通过Context.xxx API访问。

  • 这部分数据都是应用私有的,理论上只有App自己才能够访问这些数据。

  • 在应用程序被卸载时,内部存储的所有数据会被系统删除。

内部存储有2个重要目录

  • /data/app:所有安装的app的apk文件

  • /data/data:data目录存储私有数据

    • data/data/包名/files 文件信息

    • data/data/包名/cache 缓存信息

    • data/data/包名/databases 数据库信息

    • data/data/包名/shared_prefs SharedPreferences信息

默认情况下,保存到内部存储的文件是应用的私有文件,其他应用和用户不能访问这些文件。可以直接在设备的内部存储中保存、创建文件,而不需要任何访问权限。

  • Context.MODE_APPEND:该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。

  • Context.MODE_PRIVATE:默认操作模式,代表该文件是私有数据,只能被应用本身访问。在该模式下,写入的内容会覆盖原文件的内容。

Context.getDir(String name, int mode)
getDir("Joe", Context.MODE_APPEND).mkdirs()
// getDir(): /data/data/com.joe.kotlin/app_Joe

Context.getFilesDir()
// getFilesDir(): /data/data/com.joe.kotlin/files

Context.getCacheDir()
// getCacheDir(): /data/data/com.joe.kotlin/cache

Context.getDataDir() // API等级需要大于24才可以调用

内部存储的文件读写实例

    private fun writeDataByInternalStorage(data: ByteArray, name: String, mode: Int) {
        openFileOutput(name, mode).use {
            it.write(data)
        }
    }

    private fun readDataByInternalStorage(name: String): String {
        val bas = ByteArrayOutputStream()
        bas.use {
            openFileInput(name).use {
                val buff = ByteArray(1024)
                var len = it.read(buff)
                while (len > 0) {
                    bas.write(buff, 0, len)
                    len = it.read(buff)
                }
                return bas.toString()
            }
        }
    }

External File Storage 应用外部存储

应用外部私有存储

  • 外部私有存储属于应用独有,一般不会主动向外部提供数据。

  • 其他应用可以通过类似绝对路径这样的方式访问该部分数据。

  • 系统会在App卸载时移除外部私有存储中相关应用的数据。

在Android 4.4之后,访问应用外部私有存储不需要进行权限的申请。所有数据在/storage/emulated/0/Android/包名/文件下。

Environment的相关常量

  • DIRECTORY_ALARMS:系统提醒铃声存放的标准目录
  • DIRECTORY_DCIM:相机拍摄照片和视频的标准目录
  • DIRECTORY_DOWNLOADS:下载的文件标准目录
  • DIRECTORY_MOVIES:电影存放的标准目录
  • DIRECTORY_MUSIC:音乐存放的标准目录
  • DIRECTORY_NOTIFICATIONS:系统通知铃声存放的标准目录
  • DIRECTORY_PICTURES:图片存放的标准目录
  • DIRECTORY_PODCASTS:系统广播存放的标准目录
  • DIRECTORY_RINGTONES:系统铃声存放的标准目录
Context.getExternalFilesDir(null)
// getExternalFilesDir: /storage/emulated/0/Android/data/com.joe.kotlin/files

Context.getExternalFilesDirs(null)
// getExternalFilesDirs[0]: /storage/emulated/0/Android/data/com.joe.kotlin/files
// getExternalFilesDirs[1]: null

Context.getExternalFilesDir(Environment.DIRECTORY_MUSIC)
// getExternalFilesDir_DIRECTORY_MUSIC: /storage/emulated/0/Android/data/com.joe.kotlin/files/Music

Context.getExternalFilesDir(Environment.DIRECTORY_MOVIES)
// getExternalFilesDir_DIRECTORY_MOVIES: /storage/emulated/0/Android/data/com.joe.kotlin/files/Movies

Context.getExternalCacheDir()
// getExternalCacheDir: /storage/emulated/0/Android/data/com.joe.kotlin/cache

Context.getExternalCacheDirs()
// getExternalCacheDirs[0]: /storage/emulated/0/Android/data/com.joe.kotlin/cache
// getExternalCacheDirs[1]: null

Context.getExternalMediaDirs()
// getExternalMediaDirs[0]: /storage/emulated/0/Android/media/com.joe.kotlin
// getExternalMediaDirs[1]: null

应用外部共有存储

  • 一般指的是/storage/emulated/0下面,也就是/data/media挂载出来的。

  • 除去/storage/emulated/0/Android之外的所有路径,比如storage/emulated/0/Pictures这些文件夹。

  • 也包括外置sdcard,通过OTG挂载USB出来的存储,一般路径为/storage/xxxx-xxxx。

外部共有存储的路径跟应用本身没有关系,所以一般都是通过Environment类进行获取。而这些存储的数据也不会随着应用的卸载而丢失。

在API 29 getExternalStorageDirectory()、getExternalStoragePublicDirectory()已经被废弃。

相关权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Environment.getRootDirectory() // 该目录下不可创建文件或文件夹
// getRootDirectory: /system

Environment.getDataDirectory() // 该目录下不可创建文件或文件夹
// getDataDirectory: /data

Environment.getDownloadCacheDirectory() // 该目录下不可创建文件或文件夹
// getDownloadCacheDirectory: /cache

Environment.getExternalStorageDirectory() // 可自由创建 需要读写权限
// getExternalStorageDirectory: /storage/emulated/0

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) // 可自由创建 需要读写权限
// getExternalStoragePublicDirectory_DIRECTORY_MUSIC: /storage/emulated/0/Music

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) // 可自由创建 需要读写权限
// getExternalStoragePublicDirectory_DIRECTORY_DOCUMENTS: /storage/emulated/0/Documents

检查外部存储的状态

    /* Checks if external storage is available for read and write */
    fun isExternalStorageWritable(): Boolean {
        return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
    }

    /* Checks if external storage is available to at least read */
    fun isExternalStorageReadable(): Boolean {
        return Environment.getExternalStorageState() in setOf(
            Environment.MEDIA_MOUNTED,
            Environment.MEDIA_MOUNTED_READ_ONLY
        )
    }