Android内部存储与外部存储解析

Android开发的过程中。经常会涉及到存储,之前一直没有一个整体的概念,这篇文章就是进行一个知识点的梳理。

Android的存储有:内部存储、外部存储。

想要了解这两个概念,我们先将开发软件中的DDMS打开,看File Explorer,如下:

这里写图片描述

1、内部存储

上边的data文件夹,就是内部存储。data文件夹中有两个重要的文件夹app、data。
  app文件夹存放着我们所有已安装的软件的apk文件。
  data文件夹存放以包名命名的文件夹。每个文件夹里是:
    /data/data/包名/shared_prefs
    /data/data/包名/databases
    /data/data/包名/files
    /data/data/包名/cache
  这四个文件夹,其中SharePreferenced的数据就是存在shared_prefs中。软件中的数据库文件就是存在databases中,普通文件存在files中,缓存存在cache中。

在内部存储中的数据,当相关的软件删除时,会被同时删除。

2、外部存储

图中的mnt文件夹就是外部存储,不同的手机生产厂商对应的文件夹还可能是storage文件夹。在storage文件夹中还有一个文件夹sdcard。这个就是我们平时调用获取外部存储api时获取文件夹。在这个文件夹中公有目录和私有目录。公有目录有九大类。私有目录只有Android这一个,里边也是以包名为目录的。

  在很多文章中说,内部存储就是手机自带的内存、手机出厂时已经有的内存。外部存储就是通过扩展SD卡的功能后增加的存储卡,这种是不正确的。
  早期的Android设备,的确内部存储时自带的、固定的。但是后来的手机将自身的存储扩展到了8G以及更高,许多手机也不再提供扩展SD卡功能。这时就只是在概念上把手机的存储划出了内部存储和外部存储。所以不管有没有SD卡,都有内部存储和外部存储。但是不管什么情况,访问内部存储和外部存储都用的同一套Android Api。

在外部存储中的数据,当卸载软件时,该软件存在私有目录/data/storage/Android/data/包名/ 下的数据将全部删掉。软件存在公有目录下的数据不会被删掉。

3、存储空间的操作

操作内部存储空间和外部存储空间的私有目录时,以context获取的。操作外部存储空间时,以Environmnet获取。方法总结如下:

内部存储

目录方法
/data/data/包名/filescontext.getFilesDir()
/data/data/包名/cachecontext.getCacheDir()


外部存储

目录方法
根目录Environment.getExternalStorageDirectory()
公有目录(九大公有目录)Environment.getExternalStoragePublicDirectory(String type)
私有目录
/data/storage/Android/data/包名/files
context.getExternalFilesDir(String type)
私有目录
/data/storage/Android/data/包名/cache
context.getExternalCacheDir()


其中,公有目录的type类型,我们查看源码:

/**
 * Get a top-level shared/external storage directory for placing files of a
 * particular type. This is where the user will typically place and manage
 * their own files, so you should be careful about what you put here to
 * ensure you don't erase their files or get in the way of their own
 * organization.
 * <p>
 * On devices with multiple users (as described by {@link UserManager}),
 * each user has their own isolated shared storage. Applications only have
 * access to the shared storage for the user they're running as.
 * </p>
 * <p>
 * Here is an example of typical code to manipulate a picture on the public
 * shared storage:
 * </p>
 * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
 * public_picture}
 *
 * @param type The type of storage directory to return. Should be one of
 *            {@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}. May not be null.
 * @return Returns the File path for the directory. Note that this directory
 *         may not yet exist, so you must make sure it exists before using
 *         it such as with {@link File#mkdirs File.mkdirs()}.
 */
 public static File getExternalStoragePublicDirectory(String type) {
     throwIfUserRequired();
     return sCurrentUser.buildExternalStoragePublicDirs(type)[0];
 }

可以看出九种类型是:

类型意义
Environment.DIRECTORY_MUSIC音乐保存的位置
Environment.DIRECTORY_PODCASTS用于保存podcast(博客)的音频文件
Environment.DIRECTORY_RINGTONES保存铃声的位置
Environment.DIRECTORY_ALARMS警报的铃声
Environment.DIRECTORY_NOTIFICATIONS通知音保存的位置
Environment.DIRECTORY_PICTURES下载的图片保存的位置
Environment.DIRECTORY_MOVIES电影保存的位置
Environment.DIRECTORY_DOWNLOADS下载文件保存的位置
Environment.DIRECTORY_DCIM相机拍摄的图片和视频保存的位置



其中,context.getExternalFilesDir(String type)的类型有7种,看主要源码:

/**
 * @param type The type of files directory to return. May be {@code null}
 *  for the root of the files directory or one of the following
 *            constants for a subdirectory:
 *            {@link android.os.Environment#DIRECTORY_MUSIC},
 *            {@link android.os.Environment#DIRECTORY_PODCASTS},
 *            {@link android.os.Environment#DIRECTORY_RINGTONES},
 *            {@link android.os.Environment#DIRECTORY_ALARMS},
 *            {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
 *            {@link android.os.Environment#DIRECTORY_PICTURES}, or
 *            {@link android.os.Environment#DIRECTORY_MOVIES}.
 * @return the absolute path to application-specific directory. May return
 *         {@code null} if shared storage is not currently available.
 * @see #getFilesDir
 * @see #getExternalFilesDirs(String)
 * @see Environment#getExternalStorageState(File)
 * @see Environment#isExternalStorageEmulated(File)
 * @see Environment#isExternalStorageRemovable(File)
 */
 @Nullable
 public abstract File getExternalFilesDir(@Nullable String type);

可以看出七种类型是:

类型意义
Environment.DIRECTORY_MUSIC音乐保存的位置
Environment.DIRECTORY_PODCASTS用于保存podcast(博客)的音频文件
Environment.DIRECTORY_RINGTONES保存铃声的位置
Environment.DIRECTORY_ALARMS警报的铃声
Environment.DIRECTORY_NOTIFICATIONS通知音保存的位置
Environment.DIRECTORY_PICTURES下载的图片保存的位置
Environment.DIRECTORY_MOVIES电影保存的位置

注意:这个方法是可以传一个null的参数的,表示获取的是当前目录。如果传入类型,则获取的是对应的子目录。



下边给出一个对上边讲述方法进行运用的一个工具类:

import android.content.Context;
import android.os.Environment;

public class SDUtil {

    // 判断SD卡是否被挂载
    public static boolean isSDCardMounted() {
        return Environment.MEDIA_MOUNTED.equals(
                Environment.getExternalStorageState());
    }

    // 获取内部存储文件的存储路径
    public static String getFilePath(Context context) {
        return context.getFilesDir().getPath();
    }

    // 获取内部存储缓存的存储路径
    public static String getCachePath(Context context) {
        return context.getCacheDir().getPath();
    }

    // 获取外部存储根的存储路径,因为不同的商家外部存储的绝对路径可能不同,所以用相对路径进行操作
    public static String getExternalPath() {
        if (isSDCardMounted()){
            return Environment.getExternalStorageDirectory().getAbsolutePath();
        }
        return null;
    }

    // 获取外部存储公共目录的存储路径
    public static String getExternalPublicPath(String type) {
        if (isSDCardMounted()){
            return Environment.getExternalStoragePublicDirectory(type).getAbsolutePath();
        }
        return null;
    }

    // 获取外部存储私有目录的文件的存储路径
    public static String getExternalFilePath(Context context,String type) {
        if (isSDCardMounted()){
            return context.getExternalFilesDir(type).getAbsolutePath();
        }
        return null;
    }

    // 获取外部存储私有目录的缓存的存储路径
    public static String getExternalCachePath(Context context,String type){
        if (isSDCardMounted()){
            return context.getExternalCacheDir().getAbsolutePath();
        }
        return null;
    }

}

这篇博客是一篇学习总结,如有错误的地方,请大家指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值