MAUI.NET安卓11+:如何将应用内SQLite数据库复制到下载目录?
MAUI Android SQLite 备份/恢复实现(适配安卓11+)
1. 权限配置
在Platforms/Android/AndroidManifest.xml中添加以下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
2. 核心实现代码
创建BackupService类封装备份恢复逻辑:
using System.IO; using Microsoft.Maui.Storage; using Android.Content; using Android.OS; public class BackupService { private readonly string _dbFileName = "mydb.db"; private string _dbPath => Path.Combine(FileSystem.AppDataDirectory, _dbFileName); // 导出数据库到下载目录 public async Task<bool> ExportDatabaseAsync() { try { if (!await CheckAndRequestPermissionsAsync()) return false; var downloadFolder = await FileSystem.GetFolderAsync(SpecialFolder.Downloads); var backupPath = Path.Combine(downloadFolder.Path, $"mydb_backup_{DateTime.Now:yyyyMMddHHmmss}.db"); File.Copy(_dbPath, backupPath, overwrite: true); return true; } catch (Exception ex) { Console.WriteLine($"导出失败: {ex.Message}"); return false; } } // 从用户选择的备份文件恢复数据库 public async Task<bool> RestoreDatabaseAsync() { try { if (!await CheckAndRequestPermissionsAsync()) return false; var pickResult = await FilePicker.Default.PickAsync(new PickOptions { PickerTitle = "选择数据库备份文件", FileTypes = new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>> { { DevicePlatform.Android, new[] { "application/x-sqlite3" } } }) }); if (pickResult == null) return false; // 注意:这里需关闭所有已打开的数据库连接,避免文件被占用 // 示例(若用SQLite-net):await _sqliteConnection.CloseAsync(); using (var sourceStream = await pickResult.OpenReadAsync()) using (var targetStream = File.OpenWrite(_dbPath)) { await sourceStream.CopyToAsync(targetStream); } // 恢复后重新打开数据库连接(若需要) // 示例:await _sqliteConnection.OpenAsync(); return true; } catch (Exception ex) { Console.WriteLine($"恢复失败: {ex.Message}"); return false; } } // 检查并请求权限 private async Task<bool> CheckAndRequestPermissionsAsync() { if (DeviceInfo.Platform != DevicePlatform.Android) return true; var androidVersion = (int)Build.VERSION.SdkInt; if (androidVersion >= 30) { if (!Android.OS.Environment.IsExternalStorageManager) { var intent = new Intent(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission); intent.AddCategory(Intent.CategoryDefault); intent.SetData(Android.Net.Uri.Parse($"package:{Android.App.Application.Context.PackageName}")); await MainThread.InvokeOnMainThreadAsync(() => { Android.App.Application.Context.StartActivity(intent); }); await Task.Delay(2000); // 等待用户完成权限设置 return Android.OS.Environment.IsExternalStorageManager; } return true; } else { var statusRead = await Permissions.CheckStatusAsync<Permissions.StorageRead>(); var statusWrite = await Permissions.CheckStatusAsync<Permissions.StorageWrite>(); if (statusRead != PermissionStatus.Granted || statusWrite != PermissionStatus.Granted) { var result = await Permissions.RequestAsync<Permissions.StorageWrite>(); return result == PermissionStatus.Granted; } return true; } } }
3. 页面调用示例
在MAUI页面中绑定按钮事件:
private readonly BackupService _backupService = new BackupService(); private async void OnExportBtnClicked(object sender, EventArgs e) { var success = await _backupService.ExportDatabaseAsync(); await DisplayAlert("提示", success ? "备份成功" : "备份失败", "确定"); } private async void OnRestoreBtnClicked(object sender, EventArgs e) { var success = await _backupService.RestoreDatabaseAsync(); await DisplayAlert("提示", success ? "恢复成功" : "恢复失败", "确定"); }
4. 关键注意事项
- 数据库连接管理:恢复操作前必须关闭所有数据库连接,否则会因文件被占用导致复制失败,需根据你使用的SQLite库(如SQLite-net、Microsoft.Data.Sqlite)调整对应逻辑。
- 权限处理:安卓11+需
MANAGE_EXTERNAL_STORAGE权限,代码会自动引导用户到应用权限设置页面开启。 - 备份命名:代码自动添加时间戳避免覆盖备份文件,可根据需求调整命名规则。
内容的提问来源于stack exchange,提问作者user18107302
相关产品推荐
相关产品推荐

