在 Android 开发中,有两种主要类型的存储空间可供使用:私有存储空间和公共存储空间。下面是有关这两种存储空间的相关知识以及示例代码的教程:
关于权限
在 Android 开发中,如果你需要访问私有存储空间或公共存储空间,通常需要在 AndroidManifest.xml 文件中注册相应的权限。以下是注册存储权限的步骤:
1. 添加权限到 AndroidManifest.xml:
首先,在 AndroidManifest.xml 文件中添加适当的权限声明。这取决于你要访问的存储空间类型。
-
私有存储权限(
Internal Storage
):如果你的应用程序仅需要访问其私有存储空间,通常不需要额外的权限声明,因为应用程序默认有权访问自己的私有存储目录。 -
公共存储权限(
External Storage
):如果你的应用程序需要访问外部存储空间,需要声明存储权限。以下是一个示例:
<!--查看权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--写入权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--在 Android 10 中需要申明在特定情况下获得对外部存储的完全访问权限-->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- 关于 Android不同版本中的存储访问政策有关的参数
android:requestLegacyExternalStorage="true"
- 意义:此参数告诉 Android 系统启用传统的外部存储权限模式,允许应用程序访问外部存储(SD卡)的根目录以及其他应用程序的私有目录,就像在 Android 10 之前的版本中一样。
- 适用情况:如果你的应用程序在 Android 10 之前开发或迁移过来,并且需要继续以传统方式访问外部存储,则可以将此参数设置为
true
。- 注意事项:虽然这个参数允许访问传统的外部存储,但在 Android 11 和 Android 12 中,应用程序仍然需要在 AndroidManifest.xml 中声明存储权限,以确保对外部存储的访问权限。
android:requestRawExternalStorageAccess="true"
- 意义:此参数告诉 Android 系统允许应用程序使用 “raw” 文件访问模式来访问外部存储。在 “raw” 文件访问模式下,应用程序可以以类似访问私有存储空间的方式访问外部存储。
- 适用情况:如果你的应用程序需要以类似于私有存储的方式访问外部存储,例如以
File
对象的方式直接访问文件路径,那么你可以将此参数设置为true
。- 注意事项:这个参数通常用于特殊情况下,因为 Android 推荐应用程序使用存储访问框架(Storage Access Framework,SAF)来访问外部存储,以确保用户的隐私和安全性。
android:hasFragileUserData="true"
- Android 10 卸载 App 的时候,在弹出的对话框里可以由用户勾选是否保留数据。如果勾选的话,那么“外部存储 - 应用私有目录”中数据就会保留,而不会被系统清理
2. 请求运行时权限(仅限 Android 6.0 及更高版本):
从 Android 6.0(API级别23)开始,应用需要在运行时请求危险权限。你可以使用以下步骤来请求存储权限:
检查权限是否已授予: 在运行时之前,首先检查应用是否已被授予所需的权限。可以使用以下代码来检查权限状态:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 权限未授予,需要请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE);
} else {
// 权限已授予,可以执行操作
}
处理权限请求结果: 当用户授权或拒绝权限请求时,系统会调用 onRequestPermissionsResult
方法。你可以在该方法中处理授权结果。
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 权限已授予,可以执行操作
} else {
// 权限被拒绝,可能需要向用户解释为什么需要权限
}
}
}
通过这些步骤,你可以在 Android 应用程序中注册和请求存储权限,以便在访问私有存储空间或公共存储空间时确保应用程序的正常运行。请注意,权限请求和处理逻辑应该根据你的应用程序需求进行调整,以确保用户的数据隐私和安全。
使用步骤
以下是在 Android 开发中使用外部存储空间和内部存储空间的步骤,分别以表格的形式展示:
外部存储空间(External Storage)
步骤 | 描述 | 代码示例与注释 |
---|---|---|
1. 检查外部存储状态 | 在访问外部存储之前,检查外部存储的状态以确保它可用。 | java String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // 外部存储可用 } else { // 外部存储不可用或只读 } |
2. 获取外部存储目录 | 使用 Environment.getExternalStorageDirectory() 方法获取外部存储的根目录。 | java File externalStorageDir = Environment.getExternalStorageDirectory(); |
3. 创建存储目录 | 如果需要,可以创建应用程序专用的存储目录。 | java File myDir = new File(externalStorageDir, "MyAppData"); myDir.mkdirs(); // 创建目录 |
4. 写入文件到外部存储 | 使用文件输出流将数据写入外部存储的文件。 | java String fileName = "my_file.txt"; String content = "Hello, World!"; File file = new File(myDir, fileName); try { FileOutputStream fos = new FileOutputStream(file); fos.write(content.getBytes()); fos.close(); } catch (IOException e) { e.printStackTrace(); } |
5. 从外部存储读取文件 | 使用文件输入流从外部存储的文件中读取数据。 | java try { FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String line; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { sb.append(line); } fis.close(); String fileContent = sb.toString(); } catch (IOException e) { e.printStackTrace(); } |
内部存储空间(Internal Storage)
步骤 | 描述 | 代码示例与注释 |
---|---|---|
1. 获取内部存储目录 | 使用 getFilesDir() 方法获取应用程序的私有存储目录。 | java File internalStorageDir = getFilesDir(); |
2. 写入文件到内部存储 | 使用文件输出流将数据写入内部存储的文件。 | java String fileName = "my_file.txt"; String content = "Hello, World!"; try { FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE); fos.write(content.getBytes()); fos.close(); } catch (IOException e) { e.printStackTrace(); } |
3. 从内部存储读取文件 | 使用文件输入流从内部存储的文件中读取数据。 | java try { FileInputStream fis = openFileInput(fileName); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String line; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { sb.append(line); } fis.close(); String fileContent = sb.toString(); } catch (IOException e) { e.printStackTrace(); } |
这些步骤分别介绍了如何在 Android 开发中使用外部存储空间和内部存储空间进行文件读写操作。请根据你的应用程序需求选择适当的存储空间,并确保处理权限和异常以确保数据的安全性和正确性。
关于使用
1. 私有存储空间(Internal Storage):
私有存储空间是每个应用程序独占的,其他应用程序无法访问。这是最安全的存储选项,用于存储应用程序的私有数据,如设置、数据库、缓存等。私有存储空间位于应用程序的 /data/data/包名
目录下。通常情况下context类
都是控制 /data/data/包名
目录相关的内容,更多方法可以通过官方文档:https://developer.android.com/reference/android/content/Context#getDir(java.lang.String,%20int)。
获取私有存储目录:
File internalStorageDir = context.getFilesDir();
示例代码 - 写入和读取文件:
// 写入文件到内部存储
String fileName = "my_file.txt";
String content = "Hello, World!";
try {
FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(content.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
// 从内部存储读取文件
try {
FileInputStream fis = openFileInput(fileName);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
fis.close();
String fileContent = sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
2. 公共存储空间(External Storage):
公共存储空间是可以被多个应用程序访问的,例如存储在设备的外部存储卡上。这种存储空间适用于需要与其他应用程序或用户共享的文件,如照片、音乐、文档等。公共存储空间位于 /storage/emulated/0
目录下,也可以在/sdcard
目录下找到,这两个目录是映射关系。通常情况下Environment类
都是控制 /storage/emulated/0
目录相关的内容。更多相关方法可以通过官方文档查阅:https://developer.android.com/reference/android/os/Environment
检查外部存储状态:
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// 外部存储可用
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// 外部存储只读
} else {
// 外部存储不可用
}
获取公共存储目录:
File externalStorageDir = Environment.getExternalStorageDirectory();
示例代码 - 写入和读取文件:
// 检查外部存储是否可写
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File externalDir = Environment.getExternalStorageDirectory();
File myDir = new File(externalDir, "MyAppData");
myDir.mkdirs(); // 创建目录
String fileName = "my_file.txt";
String content = "Hello, World!";
File file = new File(myDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(content.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
// 从外部存储读取文件
try {
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
fis.close();
String fileContent = sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
需要注意的是,在使用外部存储时,你需要请求适当的运行时权限(如写入外部存储权限)。另外,Android 10(API级别29)及更高版本引入了存储权限更改,需要使用不同的方法来访问外部存储,以确保数据隐私和安全性。请根据应用程序的目标版本和需求来处理存储权限。
若你遇到问题创建或查看目录或文件无法操作,一查运行日志报:No such file or directory,然后检查了一圈发现权限在AndroidManifest.xml 文件中添加,为什么还是不正常运行呢???
答:虽然你代码设置了权限,但是在虚拟机或手机上你是否真的给予了授权呢?快检查你的手机上应用设置的权限吧
比较存储空间
比较项 | 公共存储空间 | 私有存储空间 |
---|---|---|
定义 | 由系统管理和分配的供所有用户共享的存储空间 | 由用户自己管理的、供自己使用的存储空间 |
访问权限 | 所有用户都可以访问和操作 | 只有拥有者可以访问和操作 |
数据安全性 | 数据可能被其他用户访问和修改 | 数据仅对拥有者可见,具有较高的安全性 |
容量限制 | 有容量限制,通常根据设备配置来分配 | 具有无限的容量,根据用户的需求进行分配 |
使用方式 | 登陆app的多个用户可以同时共享和使用 | 仅供单个登陆app用户使用 |
数据共享 | 可以被多个用户共享 | 只能由拥有者共享 |
数据持久性与生命周期 | 数据可能随时被修改或删除,不保证持久性,即使应用被卸载,只要用户不删数据仍存在 | 数据可以长期保存,除非主动删除或空间不足,应用卸载后,数据会被删除 |
用户控制 | 用户可以直接操作文件 | 用户无法访问应用私有数据 |
性能 | 低 | 高 |
适用场景 | 相册、音乐、文档等,存储大容量的数据 | 文件管理器、短信、通话记录等,存储私密数据 |