Android 28(Pie)系统下如何将SQLite数据库直接存储到SD卡
问题解决方法
1 修复当前闪退错误
你崩溃的直接原因是SQLiteOpenHelper构造方法的第四个参数要求传入数据库版本号,你错误传入了SQLiteDatabase.OPEN_READWRITE,这个常量的本身取值就是0,触发了系统对版本号必须≥1的校验规则,直接把该参数改回你原本定义的DATABASE_VERSION即可,注意该常量的取值要保证≥1。
2 API 28(Android 9)外部存储适配
2.1 清单文件补充配置
你已经添加了读写外部存储的静态权限,还需要在AndroidManifest.xml的<application>标签内添加如下属性,关闭分区存储的默认限制:
android:requestLegacyExternalStorage="true"
2.2 动态权限申请
Android 6.0及以上版本中,读写外部存储属于危险权限,仅在清单文件声明无效,必须在代码中主动发起权限申请,等用户同意授权后再初始化数据库实例。
2.3 存储路径选择
不要直接往Environment.getExternalStorageDirectory()根目录写入文件,Android 9之后对根目录写入有严格限制,优先选择公共目录存储,比如Download、Documents目录,这类目录不需要root就能被系统文件管理器直接访问。
3 完整实现代码
3.1 DatabaseHelperClass构造函数修改
import android.os.Environment; import java.io.File; public DatabaseHelperClass (Context context){ // 选择公共下载目录作为数据库存储路径 String dbPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + DATABASE_NAME; super(context, dbPath, null, DATABASE_VERSION); }
3.2 动态权限申请示例(在Activity中调用)
// 权限申请请求码 private static final int PERMISSION_REQ_CODE = 1001; // 检查权限,同意后再初始化数据库 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQ_CODE); } else { // 权限已同意,初始化数据库 DatabaseHelperClass dbHelper = new DatabaseHelperClass(this); } // 权限申请结果回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQ_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { DatabaseHelperClass dbHelper = new DatabaseHelperClass(this); } } }
其他注意事项
- 如果需要应用卸载时自动清除数据库文件,可以选择存到应用专属的外部存储目录:
context.getExternalFilesDir(null).getAbsolutePath(),该路径同样不需要root即可通过文件管理器访问,默认路径为Android/data/你的应用包名/files/下 - 如需适配Android 10及更高版本系统,建议切换到SAF(存储访问框架)实现外部存储写入,兼容性比申请legacy权限更好
内容的提问来源于stack exchange,提问作者Digital01
相关产品推荐
相关产品推荐

