当前位置:首页 > 行业动态 > 正文

安卓存储数据

安卓存储数据分内部(应用专属,卸载即删)和外部(如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);

关键注意事项

  1. 运行时权限管理

    • Android 6.0+需动态申请READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE
    • Android 10+建议使用MediaStoreAPI替代直接文件操作
    • Scoped Storage模式下外部存储分为应用专属目录和公共目录
  2. 数据安全策略
    | 风险等级 | 防护措施 |
    |———-|————————————————————————–|
    | 低风险 | 使用MODE_PRIVATE模式存储,避免明文存储敏感信息 |
    | 中风险 | 对文件内容进行AES加密,使用getSecureFilesDir()存储密钥 |
    | 高风险 | 结合Keystore API存储加密密钥,启用文件完整性校验(如MD5哈希) |

  3. 存储空间管理

    • 定期清理过期缓存:context.deleteCache(null)
    • 监控存储容量:StatFs类获取剩余空间
    • 大文件分块写入:使用BufferedOutputStream避免OOM

常见问题与解决方案

问题1:外部存储文件被系统清理工具删除

原因:部分厂商定制系统会定期清理应用安装目录下的文件
解决方案

  1. 将重要文件存储在getExternalFilesDir()返回的专用目录
  2. 添加.probe后缀文件标记正在使用状态
  3. 提供文件备份恢复机制

问题2:SQLite数据库多线程并发异常

原因:多个线程同时执行写操作导致数据损坏
解决方案

  1. 使用SQLiteDatabase.synchronized方法封装数据库操作
  2. 采用ContentProvider统一管理数据库访问
  3. 开启事务处理:db.beginTransaction()db.setTransactionSuccessful()db.endTransaction()

扩展知识问答

Q1:如何在不申请MANAGE_EXTERNAL_STORAGE权限的情况下访问任意路径文件?
A1:Android 10+系统已取消该权限,可通过以下方式替代:

  • 使用Storage Access Framework(SAF)的Intent.ACTION_OPEN_DOCUMENT
  • 请求READ_MEDIA_IMAGES等细分权限(仅限特定类型文件)
  • 通过MediaStoreAPI操作媒体文件

Q2:SharedPreferences存储大量数据会导致什么问题?
A2:主要存在两个风险:

  1. 性能问题:单个文件超过1MB时读取速度显著下降
  2. 数据丢失风险:apply()异步提交可能因进程崩溃导致未保存
    优化方案
  • 拆分为多个命名空间(如getSharedPreferences("config1", MODE_PRIVATE)
  • 对超过100条记录的配置使用数据库存储
  • 重要配置使用commit()同步
0