从通过Intent.ACTION_GET_CONTENT打开的文件中检查SQLite版本

时间:2016-02-09 02:35:27

标签: android sqlite android-intent

人, 我遇到了这个帖子中描述的问题: android-could-not-open-database

但我的问题完全不同,因为我试图打开的文件是通过Intent选择的。

我的清单中有权限集:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

当我尝试获取数据库时:

int version = SQLiteDatabase.openDatabase(fi.getPath(), null, SQLiteDatabase.OPEN_READWRITE).getVersion();

其中“fi.getPath()”内容为“/ document / 6195”(从“下载”文件夹中选择的文件)

我需要这个,因为我已经实现了备份/恢复功能,用户选择备份文件来覆盖数据库,但只有两个数据库具有相同的db版本(显然)时才能这样做。

我找不到这种情况,即使用Intent.ACTION_GET_CONTENT打开SQLite数据库。

我得到的错误是:

  

未知错误(代码14):无法打开数据库

代码可以在模拟器中运行,但不能在我的真实设备中运行,是什么让我想到了一个权限问题,但不确定......

如果有人在这里生活过一次从外部存储中读取SqLite文件,我将不胜感激......

感谢名单!

因为我没有任何声誉来创建答案......

已编辑(答案):

请注意,恢复验证过程使用的文件与用户选择的文件相同。几小时后我才能发现这就是问题所在。我的设备没有使用外部存储,下载的文件存储在内部。这是设备和仿真器之间的区别。然后,我更改了我的代码以创建一个临时文件,并用用户抓取的文件内容填充其内容。这样,恢复组件之后管理的文件位于临时文件夹中,不会发生权限问题。这就是重构后代码的样子:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case FILE_SELECT_CODE:
            if (resultCode == RESULT_OK) {
                Uri uri = data.getData();
                try {
                    InputStream fileInputStream = getContentResolver().openInputStream(data.getData());
                    File tempFile = File.createTempFile(uri.getLastPathSegment(), null, context.getCacheDir());

                    FileChannel originChannel = ((FileInputStream)fileInputStream).getChannel();
                    FileOutputStream destOutput = new FileOutputStream(tempFile);
                    FileChannel destChannel = destOutput.getChannel();
                    originChannel.transferTo(0, fileInputStream.available(), destChannel);

                    BackupFile file  = new BackupFile(new FileInputStream(tempFile), tempFile.getPath());
                    BackupData backupData = new SQLiteBackupData(context, file, new SQLiteBackupDataValidator(file));
                    DataSecurityEvent dataSecurityEvent = new SQLiteRecovery(backupData);
                    List<DataSecurityEvent> events = new ArrayList<DataSecurityEvent>(0);
                    events.add(dataSecurityEvent);
                    new BackupDataAsyncTask(context, events).execute();
                } catch (IOException e) {
                    e.printStackTrace();
                    ToastOnMiddle.makeText(context, context.getString(R.string.recover_fail), 
                       Integer.parseInt(context.getString(R.string.app_toast_time))).show();
                } catch (BackupDataException bde) {
                    ToastOnMiddle.makeText(context, getExceptionMessageValue(bde.getMessage()), 
                       Integer.parseInt(context.getString(R.string.app_toast_time))).show();
                }
            }
            break;
    }
    super.onActivityResult(requestCode, resultCode, data);
}

请注意,我使用FileChannel用所选文件内容填充临时文件。 我不确切地知道为什么在尝试直接从内部存储文件夹创建或打开SQLite数据库时会出现此问题。如果有人可以在下面的评论中解释,我会很高兴! =)

获得的经验教训:不要从文件选择器意图中获取数据库文件,并尝试直接使用它来创建或打开SQLite数据库。最好使用临时文件。

0 个答案:

没有答案