Android 手机存储及路径

目录

一,android手机存储分类

二,内部存储

三,外部存储

私有目录

公有目录

四,数据删除

五,权限相关

异常

文件读写异常

Android10存储变化

Android11存储变化

解决办法


一,android手机存储分类

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

如何区分内部存储和外部存储:可以从物理和逻辑区分

从物理的角度区分,内部存储就是手机自带存储空间,外部存储就是外部接入的存储空间例如SD卡

从逻辑意义上区分,data,system 目录就是手机的内部存储,而 mnt 或者 storage目录下的sdcard0指向的sdcard目录就是外部存储。如果是手机自带的外部存储被称为机身外部存储,外置的SD卡则称之为外部存储。当然两者都称为外部存储也没关系。这里描述的内部存储和机身外部存储都属于机身存储;

逻辑区分是从4.4以上版本开始的;

二,内部存储

获取内部存储路径和api对应关系

1,通过Environment

Environment.getDataDirectory()                /data

Environment.getRootDirectory()                /system

Environment.getDownloadCacheDirectory()            /data/cache

2,通过上下文Context

getCacheDir()                /data/user/0/包名/cache

getFilesDir()                  /data/user/0/包名/files

Build.VERSION_CODES.LOLLIPOP及以上版本新增的API

getDir("靓仔", MODE_PRIVATE)              /data/user/0/包名/app_靓仔

getNoBackupFilesDir()                             /data/user/0/包名/no_backup

getCodeCacheDir()                                  /data/user/0/包名/code_cache

Build.VERSION_CODES.N及以上版本新增的API

getDataDir()                                    /data/user/0/包名

特点:

1、内部存储路径中的文件是分类存储的,我们无法干涉,除了cache目录,别的目录系统不会自动创建

2、除了files目录,别的目录我们几乎都是无法手动操作的

3、别的App几乎无法访问内部存储中的数据,除了用非法手段或者我们主动暴露

4、内部存储目录下的文件夹及文件会随着app的卸载而被系统自动删除

三,外部存储

外部存储又可分为共有目录和私有目录;

私有目录

私有目录:不需要访问权限

Android 在外部存储空间中也提供了特殊目录供App存放私有文件,该路径为:/storage/emulated/0/Android/data/包名/

注意:应用安装之后/storage/emulated/0/Android/data/是没有对应的应用文件夹的,需要手动调用对应的API创建;

获取私有目录路径

getObbDir()                           /storage/emulated/0/Android/obb/包名 

getExternalCacheDir()          /storage/emulated/0/Android/data/包名/cache

getExternalFilesDir(null)       /storage/emulated/0/Android/data/包名/files

公有目录

公有目录:需要申请权限才能访问

权限:6.0以上需要动态申请

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

获取共有目录的API 29中已过时:

Api路径
Environment.getExternalStorageDirectory()  /storage/emulated/0

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)

获取共有目录,例如Download共有目录

/storage/emulated/0/Download

官方的解释:

在API级别29中不赞成使用此方法。为了提高用户隐私,不建议直接访问共享/外部存储设备。当应用定位到时 Build.VERSION_CODES.Q,此方法返回的路径不再可供应用直接访问。应用程序可以继续访问内容通过迁移到替代品,如存储在共享/外部存储 Context#getExternalFilesDir(String), MediaStoreIntent#ACTION_OPEN_DOCUMENT

注意:如果手机插入SD卡,可通过getExternalFilesDirs或getExternalCacheDirs遍历来获取路径;

四,数据删除

CLEAR DATA(删除数据): 清除的是 data/data/对应程序包名 的文件夹下的所有的文件全都会被删除,mnt/sdcard/Android/对应程序包名 下的所有的数据也都会被删除。

CLEAR CACHE(清空缓存): 清除的数据是 data/data/对应程序包名/catch 目录下的数据,还有 mnt/sdcard/Android/对应程序包名/catch目录下的数据

五,权限相关

在android 6.0以前,你可以只关注外置存储是否挂载即可,但是从6.0以后,也就是M系统后,还需要判断是否有读写权限,只有具备这些权限才可以读写外置存储。


1,Context.getRootDirectory

获取路径:/system
默认存在,不可读写(除非具备root权限)

2,Environment.getDownloadCacheDirectory

获取路径:/cache
默认存在,声明权限则可读写(6.0和以后系统还需要向用户申请同意才可以)

3,Context.getFilesDir

获取路径:/data/user/0/包名/files
该目录是应用的文件存储目录,应用被卸载时,该目录一同被系统删除。默认存在,默认具备读写权限(6.0系统可以不用向用户申请)

4,Context.getCacheDir

获取路径:/data/user/0/包名/cache
该目录是应用的文件缓存目录,应用被卸载时,该目录一同被系统删除。默认存在,默认具备读写权限。不同于getFileDir,该目录下的文件在系统内存紧张时,会被清空文件,来腾出空间供系统使用,著名的图片加载库ImageLoader就是在没有外置存储读写权限时使用此文件夹。getFileDir,不会因为系统内存不足而被清空。(6.0系统可以不用向用户申请)


5,Context.getDir

获取路径:/data/user/0/应用包名/app_参数名
默认存在,可读写。分为Private等三个权限,private代表仅能自己访问。(6.0系统可以不用向用户申请)

 
6,Context.getCodeCacheDir

获取路径:/data/user/0/包名/code_cache
默认存在,可读写。(6.0系统可以不用向用户申请)

7,getNoBackupFilesDir()                             

获取路径: /data/user/0/包名/no_backup
默认存在,可读写。(6.0系统可以不用向用户申请)

8,Context.getObbDir

获取路径:/storage/emulated/0/Android/obb/包名 
该目录是应用的数据存放目录,一般被用来存放游戏数据包obb文件。默认存在,可读写(6.0系统可以不用向用户申请)

9,Context.getExternalCacheDir

获取路径:/storage/emulated/0/Android/data/应用包名/cache
默认存在,可读写。(6.0系统可以不用向用户申请)
 

10,Context.getExternalFilesDir

获取路径:(以下载目录为准) /storage/emulated/0/Android/data/应用包名/files/Download
默认存在,可读写。(6.0系统可以不用向用户申请)


11,Environment.getExternalStorageDirectory

获取路径:/storage/emulated/0
默认存在,声明权限则可读写(6.0和以后系统还需要向用户申请同意才可以)

12,Environment.getExternalStoragePublicDirectory

获取路径:/storage/emulated/0/Download(以下载目录为例)
默认存在,声明权限则可读写(6.0和以后系统还需要向用户申请同意才可以)

13,Context.getDatabasePath

获取路径:/data/user/0/包名/databases/参数名
默认不存在,可读写。(6.0系统可以不用向用户申请)

 
14,Context.getPackageCodePath

获取路径:/data/app/包名-1/base.apk
默认存在,获取apk包路径


15,Context.getFileStreamPath

获取路径:/data/data/包名/files/download(示例download)
该目录是应用的文件存储目录,应用被卸载时,该目录一同被系统删除。默认存在,默认具备读写权限(6.0系统可以不用向用户申请)


附注:

a)上述路径是通过getAbsulotePath方法获得,一般情况下等同于getPath
b)在6.0系统上,一般Java层实现对外置存储的文件操作需要向用户申请,如果用C层实现,则可以越过这种限制
c)配置compilesdk,targetsdk低于23,可以避免在6.0手机上的权限限制

异常

FileNotFoundException: /storage/emulated/0/手机录屏助手/1692321717046.mp4: open failed: EPERM (Operation not permitted)

文件读写异常

1.没有授予读写权限
2.文件路劲异常

Android10存储变化

android 10(Q)开始增加了沙盒机制,不能直接把文件保存到/sdcard目录下,只能保存到APP专属目录下;AndroidManifest.xml在标签下增加属性android:requestLegacyExternalStorage=“true”可以暂时保存到/sdcard路径下
但是在目标版本在Android 11及以上 在/sdcard下的读写就不生效了,报open failed: EPERM
(Operation not permitted) 错误,追寻原因,发现在Android 11中 File.mkdirs() 一直是false,就连文件夹都创建不了,更别提文件操作。

Android11存储变化

最后查找到原因: 由于Android 11范围的存储被强制执行。针对Android 10(API级别29)的应用程序仍然可以请求requestLegacyExternalStorage属性。此标志允许应用程序暂时退出与作用域存储相关的更改,例如授予对不同目录和不同类型媒体文件的访问权限。将应用程序更新为目标Android 11后,系统将忽略requestLegacyExternalStorage标志。在 API 级别 29 中,不推荐直接访问共享/外部存储设备。当应用定位到Build.VERSION_CODES时。AndroidQ,从getExternalStorageDirectory() 方法返回的路径不再可直接被应用程序访问。应用可以通过迁移到 Context#getExternalFilesDir(String)、MediaStore 或 Intent#ACTION_OPEN_DOCUMENT 等替代项来继续访问存储在共享/外部存储上的内容。

解决办法

最终的解决方案:在 API 级别 30(Android11) 及以上,不要在 /sdcard 外部路径下存储资源 ,使用内部存储路径操作资源。

private String getSavePath() {
        String rootDir;
        if (Build.VERSION.SDK_INT > 29) {
            rootDir= mContext.getExternalFilesDir(null).getAbsolutePath() + "/手机录屏助手/";
        } else {
            rootDir= Environment.getExternalStorageDirectory().getPath() + "/手机录屏助手/";
        }
        File file = new File(rootDir);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return null;
            }
        }
        return rootDir;
}

虽然解决了FileNotFoundException: /storage/emulated/0/手机录屏助手/1692321717046.mp4: open failed: EPERM (Operation not permitted)异常,但依然存在如下问题:
这样就可以在不报错的情况下做文件存储,但是高版本保存图片或视频路径在getExternalFilesDir(null)下,即图片和视频在内部存储下,没法直接共享于手机相册中;

Environment.getExternalStorageDirectory() 是/ storage/emulated/0 

getExternalFilesDir(null) 是/storage/emulated/0/Android/data/包名/files

Environment.getExternalStorageDirectory()已过时,替代API为Context#getExternalFilesDir(null)

官方关于存储的文档:

https://developer.android.com/training/data-storage/use-cases?hl=zh-cn

  • 7
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要获取Android设备的内部存储中的picture目录,可以使用以下步骤: 1. 首先,需要在AndroidManifest.xml文件中添加读取存储权限。在<manifest>标签内添加以下权限声明: <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 2. 在你的Activity中,可以使用以下代码获取内部存储的picture目录的路径: String picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath(); 3. 使用这个picturePath变量可以进行文件操作,如读取或写入图片文件。 ### 回答2: 在Android中,要获取内部存储中的picture目录,可以使用以下代码: ```java File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); ``` 上述代码中,`Environment.getExternalStoragePublicDirectory()`方法用于获取公共的外部存储目录。参数`Environment.DIRECTORY_PICTURES`指示返回图片目录。 返回的`picturesDir`是一个`File`对象,代表内部存储中的图片目录。你可以通过该对象执行各种文件操作,例如创建文件、删除文件、检查文件是否存在等。 请注意,在使用该代码之前,需要在AndroidManifest.xml文件中添加读取外部存储的权限。可以在`<manifest>`标签下添加以下代码: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ``` 以上是获取内部存储中的public picture目录的方法。如果要获取应用私有的图片目录,可以使用以下代码: ```java File picturesDir = getApplicationContext().getFilesDir(); ``` 上述代码中,`getFilesDir()`方法用于获取应用的内部存储目录。返回的`picturesDir`对象代表该目录。 无论是获取公共目录还是应用私有目录,都可以根据具体需求进行文件操作。 ### 回答3: 在Android中,要获取内部存储的图片目录,可以使用以下代码: 首先,需要获取到当前应用的内部存储目录的绝对路径。可以通过调用Context的getFilesDir()方法来获取: File internalStorageDir = getFilesDir(); 然后,可以在内部存储目录下创建一个名为"pictures"的文件夹,用于存放图片文件: File picturesDir = new File(internalStorageDir, "pictures"); if (!picturesDir.exists()) { picturesDir.mkdirs(); } 最后,可以通过调用picturesDir.getAbsolutePath()方法来获取该目录的绝对路径: String picturesDirPath = picturesDir.getAbsolutePath(); 这样,我们就成功获取到了内部存储中的pictures目录的路径。 需要注意的是,由于内部存储的文件默认只有当前应用可以访问,其他应用无法直接访问该目录。如果希望其他应用也能访问到这些图片文件,可以考虑将其存储在外部存储中的共享目录中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ang_qq_252390816

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值