上一篇
安卓存储数据
- 行业动态
- 2025-04-23
- 2691
安卓存储数据分内部(应用专属,卸载即删)和外部(如SD卡,需权限),支持文件、SQLite数据库(结构化存储)、SharedPreferences(键值对)等方式,不同API版本权限管理有差异
安卓存储数据的方式
安卓系统提供了多种数据存储方案,开发者可根据数据类型、安全性需求、读写频率等选择合适方式:
存储类型 | 适用场景 | 数据持久性 | 访问权限控制 |
---|---|---|---|
内部存储(Internal) | 私密配置信息、缓存数据 | 是 | 仅限本应用访问 |
外部存储(External) | 媒体文件、用户可交互数据 | 是 | 需申请READ/WRITE权限 |
SQLite数据库 | 结构化数据、复杂查询需求 | 是 | 通过权限控制数据库文件 |
SharedPreferences | 简单键值对配置 | 是 | 默认本应用私有 |
ContentProvider | 跨应用数据共享 | 是 | 通过URI权限控制 |
网络存储 | 云端同步、大文件存储 | 否(本地) | 依赖网络协议 |
具体实现方案
内部存储操作
// 写入文本文件 File file = new File(context.getFilesDir(), "config.txt"); try (FileOutputStream fos = new FileOutputStream(file)) { fos.write("key=value".getBytes()); } // 读取文件 try (FileInputStream fis = new FileInputStream(file)) { byte[] buffer = new byte[fis.available()]; fis.read(buffer); String content = new String(buffer); }
外部存储适配(Android 10+)
// 兼容Android 10+的外部存储访问 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { File file = new File(context.getExternalFilesDir(null), "media/video.mp4"); } else { File file = new File(Environment.getExternalStorageDirectory(), "media/video.mp4"); }
SQLite数据库操作
// 创建数据库帮助类 public class DBHelper extends SQLiteOpenHelper { private static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT)"; public DBHelper(Context context) { super(context, "app.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE); } }
SharedPreferences使用
// 存储配置 SharedPreferences prefs = context.getSharedPreferences("app_settings", MODE_PRIVATE); prefs.edit() .putString("language", "zh-CN") .putBoolean("auto_login", true) .apply(); // 读取配置 boolean isAutoLogin = prefs.getBoolean("auto_login", false);
关键注意事项
运行时权限管理
- Android 6.0+需动态申请
READ_EXTERNAL_STORAGE
/WRITE_EXTERNAL_STORAGE
- Android 10+建议使用
MediaStore
API替代直接文件操作 - Scoped Storage模式下外部存储分为应用专属目录和公共目录
- Android 6.0+需动态申请
数据安全策略
| 风险等级 | 防护措施 |
|———-|————————————————————————–|
| 低风险 | 使用MODE_PRIVATE
模式存储,避免明文存储敏感信息 |
| 中风险 | 对文件内容进行AES加密,使用getSecureFilesDir()
存储密钥 |
| 高风险 | 结合Keystore API存储加密密钥,启用文件完整性校验(如MD5哈希) |存储空间管理
- 定期清理过期缓存:
context.deleteCache(null)
- 监控存储容量:
StatFs
类获取剩余空间 - 大文件分块写入:使用
BufferedOutputStream
避免OOM
- 定期清理过期缓存:
常见问题与解决方案
问题1:外部存储文件被系统清理工具删除
原因:部分厂商定制系统会定期清理应用安装目录下的文件
解决方案:
- 将重要文件存储在
getExternalFilesDir()
返回的专用目录 - 添加
.probe
后缀文件标记正在使用状态 - 提供文件备份恢复机制
问题2:SQLite数据库多线程并发异常
原因:多个线程同时执行写操作导致数据损坏
解决方案:
- 使用
SQLiteDatabase.synchronized
方法封装数据库操作 - 采用
ContentProvider
统一管理数据库访问 - 开启事务处理:
db.beginTransaction()
→db.setTransactionSuccessful()
→db.endTransaction()
扩展知识问答
Q1:如何在不申请MANAGE_EXTERNAL_STORAGE权限的情况下访问任意路径文件?
A1:Android 10+系统已取消该权限,可通过以下方式替代:
- 使用
Storage Access Framework
(SAF)的Intent.ACTION_OPEN_DOCUMENT
- 请求
READ_MEDIA_IMAGES
等细分权限(仅限特定类型文件) - 通过
MediaStore
API操作媒体文件
Q2:SharedPreferences存储大量数据会导致什么问题?
A2:主要存在两个风险:
- 性能问题:单个文件超过1MB时读取速度显著下降
- 数据丢失风险:
apply()
异步提交可能因进程崩溃导致未保存
优化方案:
- 拆分为多个命名空间(如
getSharedPreferences("config1", MODE_PRIVATE)
) - 对超过100条记录的配置使用数据库存储
- 重要配置使用
commit()
同步