Android 存储空间操作

一、专属存储空间

1.1.内部存储空间

1.1.1 在专属存储空间写入一个文件:

String filename = "myfile";
String fileContents = "Hello world!";
try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) {fos.write(fileContents.toByteArray());
}

1.1.2 读取在存储存储空间的文件:

        FileInputStream fis = null;try {fis = this.openFileInput("demoFile");InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8);String fileContents = null;BufferedReader reader = new BufferedReader(inputStreamReader)fileContents = reader.readLine();Log.d("FileContents: ", fileContents);} catch (IOException e) {e.printStackTrace();}

1.1.3 获取存储空间内的文件列表:

        String[] fileList = this.fileList();

1.1.4 创建嵌套目录

        File directory = this.getFilesDir();File file = new File(directory, filename);

1.1.5 创建缓存文件

        try {File.createTempFile(filename, null, this.getCacheDir());} catch (IOException e) {e.printStackTrace();}

1.1.6 访问缓存文件

File file = new File(this.getCacheDir(), filename);

1.1.7 移除缓存文件

File file = new File(this.getCacheDir(), filename);
file.delete();//或者使用上下文的deleteFile()方法
this.deleteFile(cacheFileName);

1.2 外部存储空间

在 Android 4.4(API 级别 19)或更高版本中,应用无需请求任何与存储空间相关的权限即可访问外部存储空间中的应用专属目录。卸载应用后,系统会移除这些目录中存储的文件。

在搭载 Android 9(API 级别 28)或更低版本的设备上,只要您的应用具有适当的存储权限,就可以访问属于其他应用的应用专用文件。为了让用户更好地管理自己的文件并减少混乱,以 Android 10(API 级别 29)及更高版本为目标平台的应用在默认情况下被授予了对外部存储空间的分区访问权限(即分区存储)。启用分区存储后,应用将无法访问属于其他应用的应用专属目录。

1.2.1 验证存储空间的可用性

// Checks if a volume containing external storage is available
// 可读可写
private boolean isExternalStorageWritable() {return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}// 至少是可读的
private boolean isExternalStorageReadable() {return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ||Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
}

1.2.2 选择物理存储位置

除非该卷已满或者不可用,否则使用该卷;

File[] externalStorageVolumes =ContextCompat.getExternalFilesDirs(getApplicationContext(), null);
//[/storage/emulated/0/Android/data/zjut.edu.musicplayer/files, /storage/1514-0610/Android/data/zjut.edu.musicplayer/files]
File primaryExternalStorage = externalStorageVolumes[0];

1.2.3 访问持久性文件

File appSpecificExternalDir = new File(context.getExternalFilesDir(null), filename);

1.2.4 创建缓存文件

File externalCacheFile = new File(context.getExternalCacheDir(), filename);

1.2.5 移除缓存文件

externalCacheFile.delete();

1.2.6 媒体内容

如果应用支持使用仅在您的应用内对用户有价值的媒体文件,最好将这些文件存储在外部存储空间的应用专属目录中:

@Nullable
File getAppSpecificAlbumStorageDir(Context context, String albumName) {// Get the pictures directory that's inside the app-specific directory on// external storage.File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), albumName);if (file == null || !file.mkdirs()) {Log.e(LOG_TAG, "Directory not created");}return file;
}

1.3 查询可用空间

getAllocatableByte()方法可以查出设备可以为应用提供多少空间,getAllocatableBytes() 的返回值可能大于设备上的当前可用空间量。这是因为系统已识别出可以从其他应用的缓存目录中移除的文件。

如果有足够的空间保存您的应用数据,请调用 [allocateBytes()](https://developer.android.google.cn/reference/android/os/storage/StorageManager?hl=zh-cn#allocateBytes(java.io.FileDescriptor, long))。否则,您的应用可以请求用户从设备移除一些文件或从设备移除所有缓存文件。

// app需要10MB内部空间
private static final long NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L;
//获取存储管理器
StorageManager storageManager =getApplicationContext().getSystemService(StorageManager.class);
UUID appSpecificInternalDirUuid = storageManager.getUuidForPath(getFilesDir());
long availableBytes =storageManager.getAllocatableBytes(appSpecificInternalDirUuid);
if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) {storageManager.allocateBytes(appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP);
} else {// 请求从设备移除所有缓存文件Intent storageIntent = new Intent();storageIntent.setAction(ACTION_MANAGE_STORAGE);
}

二、共享存储空间

Android 提供用于存储和访问以下类型的可共享数据的 API:

  • 媒体内容:系统提供标准的公共目录来存储这些类型的文件,这样用户就可以将所有照片保存在一个公共位置,将所有音乐和音频文件保存在另一个公共位置,依此类推。您的应用可以使用此平台的 MediaStore API 访问此内容。
  • 文档和其他文件:系统有一个特殊目录,用于包含其他文件类型,例如 PDF 文档和采用 EPUB 格式的图书。您的应用可以使用此平台的存储访问框架访问这些文件。
  • 数据集:在 Android 11(API 级别 30)及更高版本中,系统会缓存多个应用可能使用的大型数据集。这些数据集可为机器学习和媒体播放等用例提供支持。应用可以使用 BlobStoreManager API 访问这些共享数据集。

系统会自动扫描外部存储卷,并将媒体文件添加到以下明确定义的集合中:

  • 图片(包括照片和屏幕截图),存储在 DCIM/Pictures/ 目录中。系统将这些文件添加到 MediaStore.Images 表格中。
  • 视频,存储在 DCIM/Movies/Pictures/ 目录中。系统将这些文件添加到 MediaStore.Video 表格中。
  • 音频文件,存储在 Alarms/Audiobooks/Music/Notifications/Podcasts/Ringtones/ 目录中。此外,系统还可以识别 Music/Movies/ 目录中的音频播放列表,以及 Recordings/ 目录中的录音。系统将这些文件添加到 MediaStore.Audio 表格中。录音目录在 Android 11(API 级别 30)及更低版本中不可用。
  • 下载的文件,存储在 Download/ 目录中。在搭载 Android 10(API 级别 29)及更高版本的设备上,这些文件存储在 MediaStore.Downloads 表格中。此表格在 Android 9(API 级别 28)及更低版本中不可用。

媒体库还包含一个名为 MediaStore.Files 的集合。其内容取决于您的应用是否使用分区存储(适用于以 Android 10 或更高版本为目标平台的应用):

  • 如果启用了分区存储,集合只会显示您的应用创建的照片、视频和音频文件。大多数开发者无需使用 MediaStore.Files 即可查看其他应用的媒体文件,但如果您有特定要求,则可以声明 READ_EXTERNAL_STORAGE 权限。不过,建议您使用 MediaStore API 打开您的应用尚未创建的文件。
  • 如果分区存储不可用或未使用,集合将显示所有类型的媒体文件。

2.1 请求权限

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

请勿多此一举为搭载 Android 10 或更高版本的设备请求存储相关权限。您的应用可以提供明确定义的媒体集合,包括 MediaStore.Downloads 集合,而无需请求任何存储相关权限。例如,如果您正在开发一款相机应用,您无需请求存储相关权限,因为您的应用拥有您将写入媒体库的图片。

如需访问由其他应用创建的文件,必须满足以下所有条件:

  • 您的应用已获得 READ_EXTERNAL_STORAGE 权限。
  • 这些文件位于以下任一明确定义的媒体集合中:
    • MediaStore.Images
    • MediaStore.Video
    • MediaStore.Audio

如果您的应用在搭载 Android 9 或更低版本的设备上使用,或者您的应用暂时停用分区存储,您必须请求 READ_EXTERNAL_STORAGE 权限才能访问媒体文件。如果要修改媒体文件,您还必须请求 WRITE_EXTERNAL_STORAGE 权限。

如果您的应用以 Android 10(API 级别 29)或更高版本为目标平台,为了使您的应用从照片中检索未编辑的 Exif 元数据,您需要在应用的清单中声明 ACCESS_MEDIA_LOCATION 权限,然后在运行时请求此权限。

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

2.2 检查媒体库更新

如需更可靠地访问媒体文件,尤其是在应用缓存来自媒体库的 URI 或数据时,请检查媒体库版本与上次同步媒体数据时相比是否发生了变化。如需执行此更新检查,请调用 [getVersion()](https://developer.android.google.cn/reference/android/provider/MediaStore?hl=zh-cn#getVersion(android.content.Context, java.lang.String))。返回的版本是一个唯一字符串,该字符串会在媒体库发生重大变化时随之变化。如果返回的版本与上次同步的版本不同,请重新扫描并重新同步应用的媒体缓存。

2.3 查询媒体集合

例子:查询时长超过5分钟的媒体,使用如下类似SQL的选择语句:

// Need the READ_EXTERNAL_STORAGE permission if accessing video files that your
// app didn't create.// 媒体信息容器类
class Video {private final Uri uri;private final String name;private final int duration;private final int size;public Video(Uri uri, String name, int duration, int size) {this.uri = uri;this.name = name;this.duration = duration;this.size = size;}
}
//媒体列表
List<Video> videoList = new ArrayList<Video>();
//判断版本
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {//老版本方法collection = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}String[] projection = new String[] {MediaStore.Video.Media._ID,MediaStore.Video.Media.DISPLAY_NAME,MediaStore.Video.Media.DURATION,MediaStore.Video.Media.SIZE
};
//媒体时长超过
String selection = MediaStore.Video.Media.DURATION +" >= ?";
//选择参数 5分钟:300s
String[] selectionArgs = new String[] {String.valueOf(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
};
//根据文件名升序排列
String sortOrder = MediaStore.Video.Media.DISPLAY_NAME + " ASC";try (Cursor cursor = getApplicationContext().getContentResolver().query(collection,projection,selection,selectionArgs,sortOrder
)) {//获取列号int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);int nameColumn =cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);int durationColumn =cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION);int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);while (cursor.moveToNext()) {//读取各行信息long id = cursor.getLong(idColumn);String name = cursor.getString(nameColumn);int duration = cursor.getInt(durationColumn);int size = cursor.getInt(sizeColumn);Uri contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);// Stores column values and the contentUri in a local object// that represents the media file.videoList.add(new Video(contentUri, name, duration, size));}
}

Android 文件存储相关推荐

  1. android 数据文件存储,实例详解Android文件存储数据方式

    总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络.下面通过本文给大家介绍android文件存储数据方式. 1.文件存储数据使用了java中的io操作来进行文件的保存和读取,只不 ...

  2. android文件存储数组,Android面试简录——文件存储

    * SharedPreferences 请描述Android SDK支持哪些文件存储技术? 1.SharedPreferences保存key-value类型的数据 2.流文件存储(openFileOu ...

  3. android 文件存储 集合,Android 文件存储的基本使用

    在Android中我们大多数情况下我们用的都是绝对路径: 文件存储位置说明: 内部存储不是内存,内部存储位于系统中很特殊的一个位置,当应用被卸载后,内部存储的文件夹也被删除,一个应用所创建的所有文件都 ...

  4. Android文件存储方式之openFileOutput与获取数据openFileInput

    一般存储数据无非分为SP存储和数据库还有文件存储,这里我们说下文件存储openFileOutput和取出数据openFileInput 我们在一不小心退出APP如果再无退出之前不将数据保存的话数据是会 ...

  5. Android 文件存储-图片存储

    因 Android1 1谷歌禁止使用requestLegacyExternalStorage ,故将存储方式分为两种方式来进行文件存储. 存储你的应用打算与其他应用共享的文件,包括媒体.文档和其他文件 ...

  6. android 文件存储基础

    要搞清楚文件存储首先需要知道内存 和外存的定义 内存: 在任何时候都是可用的, 默认情况你存储的文件只有你自己的应用可用访问 当用户卸载app时候,系统删除所有内存中保存的文件 外存:不总是可以使用的 ...

  7. 转:彻底搞懂Android文件存储---内部存储,外部存储以及各种存储路径解惑

    转自:https://blog.csdn.net/u010937230/article/details/73303034 前言: 对于任何一个应用来说,无论是PC端应用还是Android应用,存储肯定 ...

  8. Android文件存储---内部存储,外部存储以及各种存储路径解惑

    本文转自:https://blog.csdn.net/u010937230/article/details/73303034 前言: 对于任何一个应用来说,无论是PC端应用还是Android应用,存储 ...

  9. android文件存储教程,android开发基础教程—文件存储功能实现

    文件存储: public class MainActivity extends Activity { EditText mname, mage; TextView mtv; @Override pro ...

最新文章

  1. 实例规格 ECS (共享计算型)和 (通用型-原独享)性能上有什么区别?...
  2. 使用E-MapReduce服务将Kafka数据导入OSS
  3. lvm扩张与收缩小结
  4. Kibana查询说明
  5. 删除隐藏版本信息 版本回退_Git系列之-分布式版本控制Git详解
  6. ‘StreamTableDescriptor‘ object has no attribute ‘register_table_sink‘
  7. ASP.NET 开发人员不必担心 Node 的五大理由
  8. HardSoft-Viewer PHP_index.php
  9. .NET网络编程学习(一)
  10. ecshop 模板标签
  11. 响应式布局技术:App如何适配不同尺寸的设备
  12. 老电脑应该怎么重装系统比较好
  13. vue从哪看组件版本_VUE源码解析之路
  14. 【软件测试】自动化测试到底怎么做(单元测试自动化,接口自动化,UI自动化)
  15. python点击屏幕坐标获取_python+appium 点击屏幕坐标操作(qq头像为例)
  16. PR片头片尾模板 蝴蝶飞舞动态粒子爆炸效果logo展示pr视频模板
  17. 计算机频率原理,频率计数器的工作原理和发展
  18. Jetbrain学生包续订
  19. Unity3d+Gameframework:entity实体代码分析,基于StarForce
  20. 数字孪生城市,智慧城市可视化技术解决方案案例

热门文章

  1. 软件测试计划怎么制定?
  2. 赞一下微软的自动对联(重发)
  3. BZOJ5042: LWD的分科岛
  4. 机器学习实现了脑机语言翻译,那距离“意念交流”还有多远?
  5. 均值场博弈_平均场博弈论数值算法之系数法
  6. 计算机专业及各种证书考试,各种计算机认证考试的比较
  7. matlab解整数方程,用matlab怎样解方程组的整数解
  8. 大四阶段的社会实践的主要目的是_2020关于大四暑假社会实践报告5篇
  9. msde能连mysql吗_关于MSDE安装不了的解决方法
  10. android 自定义view之掷骰子小人走动的游戏