首先分类

分为内部存储和外部存储。

内部存储:

目录   /data/data/包名。应用删除后会被主动删除。只有当前应用可访问。
    Log.v(TAG,"内部目录");        Log.v(TAG , Environment.getDataDirectory().getAbsolutePath() ); //根目录        Log.v(TAG , getFilesDir().getAbsolutePath());        Log.v(TAG , getCacheDir().getAbsolutePath());

输出结果为:

12-26 20:14:04.881 11336-11336/? V/MainActivity: 内部目录12-26 20:14:04.881 11336-11336/? V/MainActivity: /data12-26 20:14:04.881 11336-11336/? V/MainActivity: /data/data/com.touch.www.android.coolreader/files12-26 20:14:04.881 11336-11336/? V/MainActivity: /data/data/com.touch.www.android.coolreader/cache

如果您想要缓存一些数据,而不是永久存储这些数据,应该使用 getCacheDir() 来打开一个 File,它表示您的应用应该将临时缓存文件保存到的内部目录。
需要注意的是:
当设备的内部存储空间不足时,Android 可能会删除这些缓存文件以回收空间。 但您不应该依赖系统来为您清理这些文件, 而应该始终自行维护缓存文件,使其占用的空间保持在合理的限制范围内(例如 1 MB)。 当用户卸载您的应用时,这些文件也会被移除。

如果想查看内部目录文件
,开发中查看内部目可使用此种方法,规避权限问题:

###### adb shell###### run-as 包名

然后就可以使用 ls之类的命令查看内部存储结构。

下面是一个在内部文件中写入的方法。openFileOutput()是系统提供的方法。

        String str = "hello world\n";        String FILENAME = "hello_file";        FileOutputStream fileOutputStream = null;        try {            fileOutputStream = openFileOutput(FILENAME, MODE_PRIVATE);            fileOutputStream.write(str.getBytes());        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            if(fileOutputStream != null){                try {                    fileOutputStream.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }

外部存储:

外部存储是在SD卡或者手机rom分出来的部分区域里。
目录为 /storage/emulated/0/Android/data/包名/
或者/storage//Android/data/ 之类
外部存储是不安全的,任何应用都可以访问你在外部存储中的文件。

访问外部目录:

Log.v(TAG, Environment.getExternalStorageDirectory().getAbsolutePath());Log.v(TAG, getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath());

输出为:

12-26 20:14:04.881 11336-11336/? V/MainActivity: 外部目录12-26 20:14:04.881 11336-11336/? V/MainActivity: /storage/emulated/012-26 20:14:04.891 11336-11336/? V/MainActivity: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files/Pictures

其中 通过getExternalStorageDirectory访问得到的是外部存储的根目录。在根目录下建立的文件,是不会随着app的移除而被删除的。
如果你想保存照片之类的东西,并且想使得文件不随着你的app的移除而移除,可使用:
getExternalStoragePublicDirectory() 方法获取表示外部存储设备上相应目录的 File。 该方法使用指定您想要保存以便它们可以与其他公共文件在逻辑上组织在一起的文件类型的参数,比如 DIRECTORY_MUSIC 或 DIRECTORY_PICTURES。

例如,您可以使用以下方法来创建个人相册的目录:

public File getAlbumStorageDir(Context context, String albumName) {    // Get the directory for the app's private pictures directory.    File file = new File(context.getExternalFilesDir(            Environment.DIRECTORY_PICTURES), albumName);    if (!file.mkdirs()) {        Log.e(LOG_TAG, "Directory not created");    }    return file;}

通过getExternalFilesDir(XXX)得到或者建立的目录 会随着app的移除而被删除。

下面是一些有用的方法。

/* Checks if external storage is available for read and write */public boolean isExternalStorageWritable() {    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state)) {        return true;    }    return false;}/* Checks if external storage is available to at least read */public boolean isExternalStorageReadable() {    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state) ||        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {        return true;    }    return false;}

查询可用空间

如果您事先知道您将保存的数据量,您可以查出是否有足够的可用空间,而无需调用 getFreeSpace() 或 getTotalSpace() 引起 IOException。这些方法分别提供目前的可用空间和存储卷中的总空间。 此信息也可用来避免填充存储卷以致超出特定阈值。

但是,系统并不保证您可以写入与 getFreeSpace() 指示的一样多的字节。如果返回的数字比您要保存的数据大小大出几 MB,或如果文件系统所占空间不到 90%,则可安全继续操作。否则,您可能不应写入存储。
保存您的文件之前,您无需检查可用空间量。 您可以尝试立刻写入文件,然后在 IOException 出现时将其捕获。 如果您不知道所需的确切空间量,您可能需要这样做。 例如,如果在保存文件之前通过将 PNG 图像转换成 JPEG 更改了文件的编码,您事先将不知道文件的大小。

删除文件

您应始终删除不再需要的文件。删除文件最直接的方法是让打开的文件参考自行调用 delete()。

myFile.delete();

如果文件保存在内部存储中,您还可以请求 Context 通过调用 deleteFile() 来定位和删除文件:

myContext.deleteFile(fileName);

注:当用户卸载您的应用时,Android 系统会删除以下各项:

您保存在内部存储中的所有文件您使用 getExternalFilesDir() 保存在外部存储中的所有文件。

但是,您应手动删除使用 getCacheDir() 定期创建的所有缓存文件并且定期删除不再需要的其他文件。

rom做外部存储 和 SD卡

有时,已分配某个内部存储器分区用作外部存储的设备可能还提供了 SD 卡槽。

在使用运行 Android 4.3

和更低版本的这类设备时,getExternalFilesDir() 方法将仅提供内部分区的访问权限,而您的应用无法读取或写入 SD 卡。如果您希望在支持 Android 4.3 和更低版本的同时访问两个可能的位置,请使用支持库中的静态方法 ContextCompat.getExternalFilesDirs()

从 Android 4.4 开始

可通过调用 getExternalFilesDirs() 来同时访问两个位置,该方法将会返回包含各个位置条目的 File 数组。 数组中的第一个条目被视为外部主存储;除非该位置已满或不可用,否则应该使用该位置。在 Android 4.3 和更低版本中,此方法也会返回一个 File 数组,但其中始终仅包含一个条目。

        Log.v(TAG, "其他");        Log.v(TAG , getExternalFilesDir(null).getAbsolutePath());        File[] files = getExternalFilesDirs(null);        int i = 0;        for(File file : files){            if(file != null){                Log.v(TAG + (i++), file.getAbsolutePath());            }        }        Log.v(TAG, "V4支持包");        File[] filesV4 = ContextCompat.getExternalFilesDirs(this, null);        int j = 0;        for(File file : filesV4){            if(file != null){                Log.v(TAG + (j++), file.getAbsolutePath());            }        }

输出结果:

当设置rom上的分区 为 外部主存储的时候

12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity: 其他12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity: V4支持包12-27 18:00:23.753 18365-18365/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files12-27 18:00:23.753 18365-18365/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files

当设置SD卡为外部主存储的时候:

12-27 18:09:07.905 10676-10676/com.touch.www.android.coolreader V/MainActivity: 其他12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity: V4支持包12-27 18:09:07.907 10676-10676/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files12-27 18:09:07.907 10676-10676/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files

通过这个测试可以发现,getExternalFilesDir(null)返回的是主要外部存储的路径,不能保证是SD卡的路径还是rom上的路径。

总结

  • 外部存储 可能包括 rom上划分的部分 和 SDK部分。getExternalFilesDir(null)返回的是主要外部存储的路径,不能保证是SD卡的路径还是rom上的路径。
  • 内部存储的所有文件,和外部存储中通过getExternalFileDir()方法得到的路径下的文件在app被移除时会被删除。
  • 内部存储中 的getCacheDir()目录下的文件需要主动管理,并限制占用空间,以避免在空间不足的时候被系统删除。
  • 内部存储的删除需要mContext.delete(file)。外部文件的删除可以使用java文件的普通删除方法。
  • run-as方法可规避权限控制。
  • Environment.getDataDirectory() getCacheDir() getFileDir()
  • Environment.getExternalStorageDirectory() getExternalFilesDir() getExternalFilesDirs() ContextCompat.getExternalFilesDirs()(V4)

更多相关文章

  1. 2021-01-12 Android对apk进行签名
  2. 如何获取Android设备名称(常用ADB命令介绍)
  3. android EditText 不自动弹出键盘的方法
  4. Flutter Android启动源码分析(一)
  5. android sdk 更新速度慢的解决办法
  6. 浅谈Java中Collections.sort对List排序的两种方法
  7. NPM 和webpack 的基础使用
  8. Python list sort方法的具体使用
  9. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程

随机推荐

  1. Android(安卓)OTA 升级之二:脚本 ota_from
  2. Qt on Android(安卓)Episode 4
  3. Android(安卓)display架构分析(六)
  4. Android(安卓)Activity底层启动过程分析
  5. Android(安卓)代理拦截系统层代码
  6. ARouter 源码学习之Compiler
  7. Android(安卓)源码环境搭建及编译
  8. Android开发--WIFI实现
  9. 详解android 通过uri获取bitmap图片并压
  10. 深入理解ActivityResultContracts--替代s