Android应用SQLite数据库加密/单表备份至Google Drive方案咨询
解决方案
方案一:加密SQLite数据库文件后备份
实现步骤
- 读取原数据库文件的二进制内容
- 使用AES对称加密算法加密文件内容(建议结合Android Keystore存储密钥,避免硬编码密钥)
- 将加密后的内容写入临时文件
- 上传临时加密文件到Google Drive
- 备份完成后删除本地临时文件
核心代码示例
加密文件方法
private File encryptDatabaseFile(File originalDbFile, String encryptionKey) throws Exception { // 创建临时加密文件 File encryptedFile = new File(getCacheDir(), "mydbname_encrypted.db"); if (encryptedFile.exists()) encryptedFile.delete(); // AES加密配置(IV建议用随机生成值,可和加密文件一起存储) SecretKeySpec keySpec = new SecretKeySpec(encryptionKey.getBytes(StandardCharsets.UTF_8), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(new byte[16])); // 读写文件并加密 try (FileInputStream in = new FileInputStream(originalDbFile); FileOutputStream out = new FileOutputStream(encryptedFile); CipherOutputStream cipherOut = new CipherOutputStream(out, cipher)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { cipherOut.write(buffer, 0, bytesRead); } } return encryptedFile; }
修改备份逻辑
// 替换原备份代码中的filePath为加密后的文件 String dbPath = getApplicationContext().getDatabasePath("mydbname.db").getAbsolutePath(); File originalDb = new File(dbPath); // 注意:encryptionKey需从安全渠道获取(如用户输入、Android Keystore) File encryptedDb = encryptDatabaseFile(originalDb, "your_secure_key_here"); driveServiceHelper.createEncryptedFile(encryptedDb).addOnSuccessListener(...); // 备份完成后清理临时文件 encryptedDb.delete();
更新DriveServiceHelper上传方法
public Task<Void> createEncryptedFile(File encryptedFile) { return Tasks.call(mExecutor, () -> { com.google.api.services.drive.model.File fileMetaData = new com.google.api.services.drive.model.File(); fileMetaData.setName("mydbname_encrypted.db"); FileContent mediaContent = new FileContent("application/octet-stream", encryptedFile); mDriveService.files().create(fileMetaData, mediaContent).execute(); return null; }); }
方案二:仅备份指定数据表(推荐)
实现步骤
- 查询目标数据表的所有数据
- 将查询结果导出为轻量格式(如CSV、JSON)或临时单表SQLite文件
- 上传导出的文件到Google Drive
核心代码示例(导出为CSV)
导出指定表的方法
private File exportTableToCsv(String tableName) throws SQLException, IOException { File csvFile = new File(getCacheDir(), tableName + "_backup.csv"); if (csvFile.exists()) csvFile.delete(); SQLiteDatabase db = SQLiteDatabase.openDatabase( getApplicationContext().getDatabasePath("mydbname.db").getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY ); Cursor cursor = db.query(tableName, null, null, null, null, null, null); try (FileWriter writer = new FileWriter(csvFile)) { // 写入表头 String[] columns = cursor.getColumnNames(); writer.write(String.join(",", columns) + "\n"); // 写入数据行 while (cursor.moveToNext()) { StringBuilder row = new StringBuilder(); for (int i = 0; i < columns.length; i++) { if (i > 0) row.append(","); row.append(cursor.getString(i)); } writer.write(row.toString() + "\n"); } } finally { cursor.close(); db.close(); } return csvFile; }
修改备份逻辑
// 导出第二张表(假设表名为table_two) File tableBackup = exportTableToCsv("table_two"); driveServiceHelper.createFileCSV(tableBackup).addOnSuccessListener(...); // 备份完成后清理临时文件 tableBackup.delete();
更新DriveServiceHelper上传方法
public Task<Void> createFileCSV(File csvFile) { return Tasks.call(mExecutor, () -> { com.google.api.services.drive.model.File fileMetaData = new com.google.api.services.drive.model.File(); fileMetaData.setName("table_two_backup.csv"); FileContent mediaContent = new FileContent("text/csv", csvFile); mDriveService.files().create(fileMetaData, mediaContent).execute(); return null; }); }
补充说明
还原数据时,只需下载CSV文件,解析内容后插入到对应数据库表即可,逻辑简单且彻底避免核心数据泄露。
内容的提问来源于stack exchange,提问作者Darksymphony
相关产品推荐
相关产品推荐

