我正在使用Intent.ACTION_GET_CONTENT
选择一个文件。
在方法onActivityResult
中,我得到了Uri:
Uri selectedfile = data.getData();
如何使用Uri对象selectedfile
打开SQLite数据库?这不起作用:
SQLiteDatabase database = SQLiteDatabase.openDatabase(selectedfile.getPath(), null, SQLiteDatabase.OPEN_READONLY);
答案 0 :(得分:0)
您不应尝试从Uri中打开SQLiteDatabase。
SQLiteDatabase旨在直接与文件系统一起使用:它需要锁定和解锁数据库文件并管理单独的预写日志记录(-shm和-wal)文件,而Uri不一定引用file://中的任何内容模式。相反,它可以是任何东西,从https://或content://到自定义应用定义的模式。
尤其是从Android 7.0开始,Google强制使用content:// uris在应用之间共享文件(这正是您的情况)。从这里获取:https://developer.android.com/about/versions/nougat/android-7.0-changes.html:
对于面向Android 7.0的应用,Android框架会实施StrictMode API策略,该策略禁止在应用外部公开file:// URI。如果包含文件URI的意图离开您的应用程序,则该应用程序将失败,并出现FileUriExposedException异常。
要在应用程序之间共享文件,应发送content:// URI并授予对该URI的临时访问权限。授予此权限的最简单方法是使用FileProvider类。有关权限和共享文件的更多信息,请参见共享文件。
相反,您应该获取ContentResolver,从中打开uri InputStream并将流内容保存到本地临时文件,然后在其上使用SQLiteDatabase.openDatabase(filePath):
void openDatabaseFromFileDialog() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*");
startActivityForResult(Intent.createChooser(intent, "Select a database"), DB_FILE_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == DB_FILE_REQUEST && resultCode == RESULT_OK) {
Uri dataUri= data.getData();
openDatabaseFromUri(dataUri);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
void openDatabaseFromUri(Uri uri) {
InputStream inputStream = application.getContentResolver().openInputStream(uri);
File file = File.createTempFile("sqlite", "");
FileOutputStream outputStream = new FileOutputStream(file);
byte[] buff = new byte[1024];
int read;
while ((read = inputStream.read(buff, 0, buff.length)) > 0)
outputStream.write(buff, 0, read);
inputStream.close();
outputStream.close();
openDatabaseFromFile(file.getPath());
}
void openDatabaseFromFile(String filePath) {
// your code here
}
另外,当您从另一个应用程序(可能是第三方)获取SQLite流时,我强烈建议您在单独的Thread / AsyncTask / etc中使用数据库。您永远不知道会收到多少PB: )