文章目录

  • 目的
  • 基础说明
  • 应用专属存储空间
  • 共享存储
  • 其它
  • 总结

目的

APP开发与使用过程中免不了和文件打交道,对于Windows或Linux而言文件的存储与访问操作都很方便,直接通过文件系统路径和文件接口操作就行。在Android中因为安全原因,这方面变得有些复杂,这篇文章将对相关内容做个梳理记录。

这篇文章的内容主要参考下面官方文档:
https://developer.android.google.cn/guide/topics/data

文件存储与访问相关操作受Android SDK API版本影响,本文编写时 target api = 31。

基础说明

Android中对于APP开发而言文件存储主要可以分为两大部分 应用专属存储空间共享存储

应用专属存储空间

应用专属存储空间又可以分为 内部存储外部存储 ,这每一块又可以分别用来存储 持久性文件缓存文件 。通常而言内部存储位于 /data/user//data/data/ 下,外部存储位于 /Android/data/ 下。持久性文件目录为 files ,缓存文件目录为 cache

需要注意的是上面的 外部 只是一种逻辑上的划分,和实际硬件的存储器组织方式无关,特别是对于现在大多数不支持扩展卡的设备而言这些区域都是位于设备内部存储器上的。

内部存储空间 - 持久性文件 使用 getFilesDir() 来获取其根目录路径:

知道路径就可以用传统的方式来操作文件了:

File file = new File(context.getFilesDir(), filename);

不过Android也可以直接操作文件,可以理解为这块空间就是默认路径:

String filename = "naisu.txt";// 写文件
String fileContents = "Hello Naisu!";
try (FileOutputStream fos = openFileOutput(filename, MODE_PRIVATE)) {fos.write(fileContents.getBytes());
}// 读文件
FileInputStream fis = openFileInput(filename);
InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8);
try (BufferedReader reader = new BufferedReader(inputStreamReader)) {// Read File
} catch (IOException e) {// Error occurred when opening raw file for reading.
} // 文件列表
String[] files = fileList();

内部存储空间 - 缓存文件 使用 getCacheDir() 来获取其根目录路径:

下面是一些缓存文件常用操作:

// 创建缓存文件
File.createTempFile(filename, null, getCacheDir());
// 访问缓存文件
File cacheFile = new File(getCacheDir(), filename);
// 删除缓存文件
cacheFile.delete(); 或 deleteFile(filename);

外部存储空间 - 持久性文件 使用 getExternalFilesDir() 来获取其根目录路径:

这里主要操作就是一般的文件操作:

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

这个目录下新建的子目录名称也可以使用预设的,比如下面代码中的 DIRECTORY_PICTURES 属于SDK定义的目录
(https://developer.android.google.cn/reference/android/os/Environment#fields):

@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;
}

在 Android 11(API 级别 30)及更高版本中这个目录有更多限制了。

外部存储空间 - 缓存文件 使用 getExternalCacheDir() 来获取其根目录路径:

这里主要操作就是一般的文件操作:

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

共享存储

现在的Android设备很多都会自带文件管理器,打开文件管理器默认可以看到 Android Download Music 等目录,对用户而言这些目录是比较常用的目录,这些目录通常位于 /storage/emulated/0/ 目录下,这个路径可以通过下面方法获取:

Environment.getExternalStorageDirectory();
// Environment.getExternalStoragePublicDirectory("");

通常来说应用与应用或应用与用户都可以访问的共享存储空间主要就是上面目录了。该目录默认设计主要用于存放媒体内容(Media),通常根据内容会分为下面几类进行存储:

  • Images 主要位于 DCIM/ Pictures/
  • Video 主要位于 DCIM/ Movies/ Pictures/
  • Audio 主要位于 Alarms/ Audiobooks/ Music/ Notifications/ Podcasts/ Ringtones/
  • Downloads 主要位于 Download/
  • Files

上面内容都是官方默认的分类,这些区域都属于MediaStore,可以有专门的方式去访问,或者也可以以文件方式访问。

在Android 10和11之前很多APP根据自己喜好来,在 /storage/emulated/0/ 下建个自己的目录,所有东西都丢里面。现在谷歌不推荐怎么来了,当然也没把路堵死,可以通过启用 MANAGE_EXTERNAL_STORAGE 权限来解锁。

共享存储空间操作通常需要声明相关权限:

<!-- Required only if your app needs to access images or photos that other apps created. -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /><!-- Required only if your app needs to access videos that other apps created. -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /><!-- Required only if your app needs to access audio files that other apps created. -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /><!-- If your app doesn't need to access media files that other apps created, set the "maxSdkVersion" attribute to "28" instead. -->
<!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"android:maxSdkVersion="32" /> -->
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"android:maxSdkVersion="29" /> -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- Android11开始,提供对应用专属目录和 MediaStore 之外文件的写入权限 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /><!-- Android10特供,停用分区存储 -->
<!-- <application android:requestLegacyExternalStorage="true"> --><!-- 如果应用是在Android11以下版本时安装,系统升级到Android11后应用将保留其之前安装时的存储结构 -->
<!-- <application android:requestLegacyExternalStorage="true"> -->

有的权限开启可能需要用户主动确认:

public void checkPermission() {// 需要用到的权限String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.MANAGE_EXTERNAL_STORAGE};if (android.os.Build.VERSION.SDK_INT >= 23) {ArrayList<String> list = new ArrayList<>();for (String item : permissions) {// 检查权限是否开启if (this.checkSelfPermission(item) != PackageManager.PERMISSION_GRANTED) {list.add(item);}}if (list.size() != 0) {String[] arr = new String[list.size()];list.toArray(arr);this.requestPermissions(arr, 233); // 开启弹窗让用户确认}}
}

下面是个关于上面内容的简单的文件操作演示:

上面演示中在应用启用时会去检查相关权限,如果权限未开启则让用户确认开启;通过定时器定时查询权限情况,如果权限开启了则建立目录与文件。注意AndroidManifest.xml中也需要添加权限

另外提一句像 /storage/emulated/0/ 这种目录下很多公共资源都可以在设备上浏览器中使用 file:///storage/emulated/0/... 进行浏览。

其它

res/raw/
在应用开发时很多资源都是放在项目工程的 res/ 目录下的,这些都会被编译成二进制文件打包到apk中,也可以在该目录下建立raw目录,即 res/raw/ 这下面也可以放置文件,且不会被编译成二进制文件。在程序中使用的话就和其它 res/ 目录下的资源一样,通过 R.id.filename 进行访问。

assets/
可以在 项目目录/app/src/main/ 下建立 assets 目录,在其中放置的资源文件也会被打包到apk中。这里的内容需要使用 AssetManager 类进行访问。还有一种使用方式是在webView中通过 myWebView.loadUrl("file:///android_asset/...") 形式进行加载。

需要注意的是这里的两个目录下的文件可能不支持大于1M的文件。

总结

本文主要讨论了Android中文件存储与访问的一些基本内容,其中稍微和其它平台不同的就是Android中对于APP可见的文件系统结构,总体来说使用起来也并不复杂。本文中没有提到存储空间检查、访问权限、存储卡以及其它很多情况,这些内容可以文章开头给出的文档链接中获取相关信息。

除了上面内容外常用的像是轻量数据和数据库、应用间数据和文件交互等内容均没有涉及,这些内容虽然最终也是以文件形式来保存数据的,但是APP开发者不用关系其具体的存储位置。这些内容可以在文章开头给出的文档链接中获取相关信息。

Android Native APP开发笔记:文件存储与访问相关推荐

  1. Android Native APP开发笔记:从新建到打包流程记录

    文章目录 目的 下载与安装 新建项目与运行调试 更换名称和图标 打包应用 applicationId 版本控制 真机调试 总结 题外话 目的 安卓是现在移动端平台占有率最大的平台,如果进行移动端用户应 ...

  2. Android Native APP开发笔记:使用WebView控件加载网页

    文章目录 目的 基础使用 处理网页导航 加载本地网页 Web和Native之间交互 调试Web应用 处理页面重绘 总结 目的 WebView是一个比较常用的控件,功能上也比较单一,就是用来加载网页的, ...

  3. Android Native APP开发笔记:双击返回键退出应用单击返回键返回桌面

    文章目录 目的 基础说明 双击返回键退出应用 单击返回键回到桌面 总结 目的 双击返回键退出应用 很早之前就是Android中非常常见的一种功能,而目前好多安卓应用为了应用常驻都改为使用 单击返回键返 ...

  4. Android移动APP开发笔记——最新版Cordova 5.3.1(PhoneGap)搭建开发环境

    引言 简单介绍一下Cordova的来历,Cordova的前身叫PhoneGap,自被Adobe收购后交由Apache管理,并将其核心功能开源改名为Cordova.它能让你使用HTML5轻松调用本地AP ...

  5. Android移动APP开发笔记——Cordova(PhoneGap)通过CordovaPlugin插件调用 Activity 实例...

    引言 Cordova(PhoneGap)採用的是HTML5+JavaScript混合模式来开发移动手机APP.因此当页面须要获取手机内部某些信息时(比如:联系人信息,坐标定位.短信等),程序就须要调用 ...

  6. Android平板app开发布局文件,Android平板开发相关

    关于系统的资源配置的目录(我只列出一些大概,默认项目会有一些资源配置目录) Android系统支持多配置资源文件,我们可以追加新的资源目录到你的Android项目中.命名规范: 资源名字-限制符 la ...

  7. android实现存储,Android开发实现文件存储功能

    本文实例为大家分享了Android开发实现文件存储的具体代码,供大家参考,具体内容如下 这个程序只有一个Activity, Activity中只有一个Edittext.实现的功能是在Activity销 ...

  8. android中资源文件的两种访问方式,Android_Android学习笔记-保存文件(Saving Files),Android设备有两种文件存储区域 - phpStudy...

    Android学习笔记-保存文件(Saving Files) Android设备有两种文件存储区域: 内部存储和外部存储 ("internal" and "externa ...

  9. 【Android】Parse开发笔记(1)—— 准备

    一.简介 Parse是由 YC 孵化出来的.专为移动应用提供后台服务的云计算平台,为开发者包办繁琐的后台服务,让开发者只需专注于具体的开发工作.它提供任意数据保存.照片或其它文件存储.发送推送通知.创 ...

最新文章

  1. 如何写第一个scrapy
  2. Spring中BeanPostProcessor
  3. qmake 没有生成.o文件_qmake实用变量
  4. rabbitnq 源码安装_linux下源码安装rabbitMq
  5. 【C++grammar】string类和array类
  6. Red Gate系列之一 SQL Compare 10.4.8.87 Edition 数据库比较工具 完全破解+使用教程
  7. js混淆还原工具_混淆过的js代码如何还原?
  8. [USACO2006][poj3182]The Grove(巧妙的BFS)
  9. vue组件中传值遇到的一些问题
  10. 基于Scrapy+MySQL爬取国家药监局100w+数据踩坑记录
  11. ug编程内公差和外公差是什么_UG编程
  12. 作为产品经理,懂接口是必须的
  13. 广西建工OA系统office插件显示问题解决方案
  14. .so文件(so文件是什么)
  15. 微信App iOS客户端不同阶段的发展策略
  16. 基于matlab的交通信号模糊控制系统设计
  17. HTML语句判断IE浏览器版本
  18. 测试管理办公室TMO职责
  19. Windows Hook 易核心编程勾子基本理念
  20. python热图_Python绘制热图

热门文章

  1. 怎么把PPT批量变成图片?
  2. 2022年双十一洗面奶选购指南
  3. Oracle中to_char函数的速度问题
  4. 2020年中国色纺纱行业市场现状分析,国内参与者呈现寡头模式「图」
  5. RecyclerView使用GridLayoutManager 设置间距一致大小
  6. MySQL基本数据类型与Java基本数据类型
  7. linux下挂载新的磁盘
  8. linux下如何挂载磁盘阵列
  9. 数字经济核心科技深度报告:AI+5G是数字时代通用技术平台
  10. python 如何爬取王者荣耀全英雄皮肤