如果最大版本是Q
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
....
android:requestLegacyExternalStorage="true"
....
>
如果最大版本是R
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
//查看是否有外置存储卡权限
externalStorageManager = Environment.isExternalStorageManager();
//没有的话
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + context.getPackageName()));
startactivityforresult(intent ,request)
android 存储路径笔记
Android手机存储分为两个部分:
内部存储和外部存储,
内部存储一般是手机自带的存储空间,外部存储指外插SD卡提供的存储空间;
随着手机发展,这两个存储的定义又有了一些些变化,新的手机不再有外插SD卡的概念,采取了内置闪存(eMMC、UFS等)的方式,所以内部存储和外部存储在新的Android手机上已经在同一个硬件上了。但为了兼容旧设备和让用户得到更好的体验,我们仍然需要管理好手机上内外存储的使用。
应用操作的文件存储位置分为 三个部分:
应用内部存储私有文件目录
应用外部存储私有文件目录
公有目录
有两种api去获取这三个部分的存储位置,它们分别归属于Context
和Environment
。
Context
Context是应用的上下文,它用来 获取与应用相关的文件目录 ,可以获取应用私有和应用公有目录,常用的api有(后面是所对应的路径):
1. Context#getCacheDir() /data/user/0/cn.appname.xxx/cache
2. Context#getDir("spanner",MODE_PRIVATE) /data/user/0/cn.appname.xxx/app_spanner
3. Context#getFileDir() /data/user/0/cn.appname.xxx/files
3. Context#getExternalCacheDir() /storage/emulated/0/Android/data/cn.appname.xxx/cache
4. Context#getExternalFilesDir(Environment.DIRECTORY_PICTURES) /storage/emulated/0/Android/data/cn.appname.xxx/files/Pictures
Context#getExternalFilesDir(null) /storage/emulated/0/Android/data/cn.appname.xxx/files
5. Context#getExternalMediaDirs() /storage/emulated/0/Android/media/cn.appname.xxx
前两个是应用内部存储私有目录,后面4个都是应用外部存储私有文件目录。注意:/data/user/0/ 等同于 /data/data/
- Environment
Environment和应用无关,它用于获取公有存储位置的文件目录,常用的api有:
1. Environment#getExternalStorageDirectory() /storage/emulated/0
2. Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) /storage/emulated/0/DCIM
Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) /storage/emulated/0/Pictures
3. Environment#getDataDirectory() /data
4. Environment#getDownloadCacheDirectory() /data/cache
5. Environment#getRootDirectory() /system
API的选用
到底什么时候要用什么api呢?
应用私有文件目录
应用私有目录由Context获取控制,分为内部存储和外部存储,内部存储不需要申请文件读写权限也能够使用,外部存储需要权限(getetExternalCacheDir() 和 getExternalFilesDir() 这两个方法从4.4之后不再需要读写权限)。用户对app进行数据清理或卸载可以清理外部存储和内部存储下的所有文件目录
内部存储
内部存储的文件夹其他应用和用户无法直接访问,可以用于存放敏感数据。
getCacheDir()
专门用于存放缓存数据。
用户对app进行缓存清理的时候会清理缓存目录cache的数据,手机空间不足的时候系统也会对缓存目录内的数据进行清理。但尽管如此,开发者仍要管理好缓存数据特别是内部存储的缓存,避免缓存数据过大。
getFileDir()
可用于用于存放私有持久文件。
非常适合用于存放app各种伴随app运行周期所需要的文件数据,它既不会因为手机存储空间不足而被清理,也不会因卸载app而遗留数据垃圾,并且它是私有的
getDir(String name,int mode)
getDir(String name,int mode)
在内部私有目录下会创建一个名为app_name的文件夹,mode以前是可以设置文件夹私有(MODE_PRIVATE)和公有的(MODE_WORLD_READABLE、MODE_WORLD_WRITEABLE),但目前公有的mode都已经废弃,意味着这个api创建的文件夹已经完全私有,不能再共享出去了。
外部存储
在Android Q之前其他应用是可以访问修改外部存储的应用私有目录的,这个要注意。 使用外部存储之前一定要检查外部存储是否可用,因为旧设备不一定会有外部存储,新手机也不一定会给你读写权限,就算用户不给你权限,你的app也要运行啊,不然就不用你的了。
public static boolean isSDCardEnable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
getExternalCacheDir()
专门用于存放缓存数据。和内部存储的getCacheDir()相似。
getExternalFilesDir(String type)
归类存放公有文件。
如果type不为null的话在外部私有目录下创建返回一个名为type的文件夹,为null直接返回外部私有根目录。如无特别需要,个人的做法是传入Environment的DIRECTORY常量进行文件夹创建。
如果看完这篇你还不会选用api,那就把你应用杂七杂八的东西都放进去吧,文件至少不用东一件西一件的,卸载之后也能够被正确清理掉,不过也要控制好占用的存储空间。
getExternalMediaDirs()
可存放共享媒体文件。
这个是在Android 5.0加入的api,创建和获取位于/sdcard/Android/media目录下的应用目录,该目录下的文件能够被其他应用访问和被MediaStore查询和获取。但目前较少开发者在使用这个api。
公有目录
获取公有目录要使用Environment的Api,它返回的目录全都是共享的公有目录。造成Android手机文件存储混乱的罪魁祸首!为数众多的无责任开发者在这里胡乱创建文件夹,乱起名、乱放文件,普通用户根本无法判断哪些文件夹、文件是有用的,卸载app之后留下庞大的无法清理的垃圾文件,导致手机空间不足。于是它们在Android Q被废弃了,但是Q之前还是能好好使用的,我认为要开始减少使用它们,更多地使用Context下的私有目录API。
getExternalStorageDirectory() - 获取外部存储(SD卡)的根目录。使用getExternalStoragePublicDirectory(String)进行替代即可。
getExternalStoragePublicDirectory(String type)
使用频率极高的api,返回在根目录下的名为type的文件夹,我把它分为两种用法:一种是传入Environment的DIRECTORY常量再创建子目录使用;一种是传入appPackageName或者易被识别归属的名称创建子目录使用。前者会比较通用,内容可以被各种工具app搜索发现(包括微信);后者算是私用,可以存放不跟随app生命的文件,即卸载后也可以保留。
Environment.DIRECTORY_DCIM是手机的相册,这个文件夹都是系统相关的app在用,存放相机拍摄的图片,手机截图之类的,不推荐开发者使用这个文件夹,避免混乱。值得一提的是淘宝有在使用这个文件夹,用于保存它的商品分享截图,这个位置的确可以避免被微信封杀~哈哈
Environment.DIRECTORY_PICTURES用于存放各种“正式的”图片,强烈建议在这里创建文件夹存放你想要被用户发现的图片,并且微信会扫描这个文件夹,让你的图片更容易分享。不过还。
Environment.DIRECTORY_DOWNLOADS可以用于存放app更新的apk等下载资源。
其他几个比较少用就不介绍了。
适配Android Q
适配Android R