文章转自本人优快云博客
目标和环境
最近项目中需要事实存储监测的数据,于是使用SQLiteOpenHelper来实现。事后又要导出到分析软件分析,所以必须将db文件放到指定的位置。SQLiteOpenHelper默认的位置只有app自己访问,想导出来很麻烦。一番搜索和试错后,终于实现功能。手机版本是android6.0,studio3.5.2。
虽然csdn上面能看到不少相关的文章,奈何google更猛。所以好多文章照着做也是失败。最后终于在stackoverflow这个问题下面k3b大佬的回复找到了解决方法。
代码
自己写的SQLiteOpenHelper类中间要有如下的改动:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 3;
.....
DatabaseHelper(final Context context, String databaseName) {
super(new DatabaseContext(context), databaseName, null, DATABASE_VERSION);
}
}
创件一个DatabaseContext类继承ContextWrapper并重写getDatabasePath和openOrCreateDatabase
class DatabaseContext extends ContextWrapper {
private static final String DEBUG_CONTEXT = "DatabaseContext";
public DatabaseContext(Context base) {
super(base);
}
@Override
public File getDatabasePath(String name) {
File sdcard = Environment.getExternalStorageDirectory();
String dbfile = sdcard.getAbsolutePath() + File.separator+ "databases" + File.separator + name;
if (!dbfile.endsWith(".db")) {
dbfile += ".db" ;
}
File result = new File(dbfile);
if (!result.getParentFile().exists()) {
result.getParentFile().mkdirs();
}
if (Log.isLoggable(DEBUG_CONTEXT, Log.WARN)) {
Log.w(DEBUG_CONTEXT, "getDatabasePath(" + name + ") = " + result.getAbsolutePath());
}
return result;
}
/* this version is called for android devices >= api-11. thank to @damccull for fixing this. */
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
return openOrCreateDatabase(name,mode, factory);
}
/* this version is called for android devices < api-11 */
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
// SQLiteDatabase result = super.openOrCreateDatabase(name, mode, factory);
if (Log.isLoggable(DEBUG_CONTEXT, Log.WARN)) {
Log.w(DEBUG_CONTEXT, "openOrCreateDatabase(" + name + ",,) = " + result.getPath());
}
return result;
}
}
理论上这样就能在指定的位置创建db文件了。
权限
光上面的代码还是不行的,还需要外部存储文件的读写权限,6.0以前只要在manifest里面添加下面这些代码
6.0及以上的就要动态申请。
首先写一个申请类
public class PermissionUtils {
private static String[] PERMISSIONS_CAMERA_AND_STORAGE = {
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.CAMERA};
public static boolean isGrantExternalRW(Activity activity, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int storagePermission = activity.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
int cameraPermission = activity.checkSelfPermission(android.Manifest.permission.CAMERA);
if (storagePermission != PackageManager.PERMISSION_GRANTED ||
cameraPermission != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(PERMISSIONS_CAMERA_AND_STORAGE, requestCode);
return false;
}
}
return true;
}
}
之后在MainActivty的onCreate下添加
PermissionUtils.isGrantExternalRW(this,1);
运行的时候授权就ok了。
关于路径
现在很多手机没有sd卡,但是依然有外部存储。只能APP访问的,就是内部存储,反之,应该是外部存储了。
不管是不是存在sd卡上,注意用正确的get方法拿到正确的路径。我这里是用Environment.getExternalStorageDirectory().getAbsolutePath()拿到根目录的。
否则很容易看到android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (Sqlite code 14)
————————————————
版权声明:本文为优快云博主「bat2fly」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/bat2fly/article/details/106122061