如何使用 Uri 对象打开现有的 SQLite 数据库?

2024-03-20

我在用着Intent.ACTION_GET_CONTENT选择一个文件。

在方法中onActivityResult我得到的 Uri:

Uri selectedfile = data.getData();

如何使用 Uri 对象selectedfile打开 SQLite 数据库?这不起作用:

SQLiteDatabase database = SQLiteDatabase.openDatabase(selectedfile.getPath(), null, SQLiteDatabase.OPEN_READONLY);

您不应该尝试从 Uri 打开 SQLiteDatabase。

SQLiteDatabase 被设计为直接与文件系统一起工作:它需要锁定和解锁数据库文件并管理单独的预写日志记录(-shm 和 -wal)文件,而 Uri 不一定引用 file:// 模式中的任何内容。相反,它可以是任何内容,从 https:// 或 content:// 到自定义应用程序定义的架构。

特别是自 Android 7.0 以来,Google 强制使用 content:// uri 在应用程序之间共享文件(这正是您的情况)。摘自这里:https://developer.android.com/about/versions/nougat/android-7.0-changes.html 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 流时,我强烈建议您在单独的线程/AsyncTask/等中使用数据库。您永远不知道您收到了多少 PB :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Uri 对象打开现有的 SQLite 数据库? 的相关文章

随机推荐