使用ACTION_OPEN_DOCUMENT_TREE选择文件夹时打开sqlite数据库

时间:2015-04-21 14:25:41

标签: android sqlite android-intent android-5.0-lollipop

我在文件夹/sdcard/myfolder/db/mydb.db中已经存在一个sqlite数据库。 我的应用程序显示了一个用于选择文件夹的对话框:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                      startActivityForResult(intent, 42);

弹出对话框,我可以选择文件夹:

enter image description here

我选择文件夹/ sdcard / myfolder / db /并按select / ok。

我的onActivityResult被调用。我查看了所有文件,如果文件是我的" mydb.db"然后我尝试用SQLiteDatabase.openDatabase()打开sqlite数据库;我收到一个错误(见下文)

我对问题的猜测: 这不起作用,因为openDatabase需要数据库的完整路径,如/sdcard/myfolder/db/mydb.db

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // if (requestCode == REQUEST_QUICKLIST) {
        if (resultCode == Activity.RESULT_OK) {
            if(requestCode==42){
                // TreeDialog for choosing the Installdirectory
                Uri treeUri = data.getData();
                DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
                for (DocumentFile file : pickedDir.listFiles()) {
                    if(file.getName().equals("mydb.db")){
                        SQLiteDatabase sqliteTest=  SQLiteDatabase.openDatabase(file.getUri().getPath(), null, SQLiteDatabase.OPEN_READONLY);   
                    }
                    Log.d("DEBUG FILE", "Found file " + file.getName() + " with size " + file.length() + " " + file.getParentFile().getName());
                }

file.getUri().getPath()的值为:/tree/primary:myfolder/db/document/primary:myfolder/db/mydb.db

如何打开sqlite数据库?

堆栈跟踪:

 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=42, result=-1, data=Intent { dat=content://com.android.externalstorage.documents/tree/primary:myfolder/db flg=0xc3 }} to activity {mycompany.browser/mycompany.browser.browser}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    at android.app.ActivityThread.deliverResults(ActivityThread.java:3976)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4019)
    at android.app.ActivityThread.access$1400(ActivityThread.java:172)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1471)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5834)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
    Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:318)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:228)
    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:512)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:891)
    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:861)
    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:671)
    at mycompany.browser.browser.onActivityResult(browser.java:1533)
    at android.app.Activity.dispatchActivityResult(Activity.java:6475)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:3972)

2 个答案:

答案 0 :(得分:2)

由于目前Lollipop设备不可用,我还没有通过测试,但这应该有效,请告诉我是否有任何问题!

if(file.getName().equals("mydb.db")){
    Uri uri = file.getUri();
    Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
                      DocumentsContract.getTreeDocumentId(uri));
    String path = ASFUriHelper.getPath(this, docUri);
    SQLiteDatabase sqliteTest=  SQLiteDatabase.openDatabase(path, null, 
                                     SQLiteDatabase.OPEN_READONLY);
}

可以在此处找到带有中间方法的ASFUriHelper.getPath()方法的要点:ASFUriHelper.getPath()

答案 1 :(得分:1)

谢谢你的回答。我的问题是当我选择SD卡上的目录时,getPath在带有SD卡的HTC M8上返回NULL。

那是因为uri在getpath代码中没有包含“primary”:

if ("primary".equalsIgnoreCase(type)) {
    return Environment.getExternalStorageDirectory() + "/" + split[1];
}

对我来说,类型包含“1AF0-170C”,完整的uri是:

/tree/1AF0-170C:SmartDiveBook/document/1AF0-170C:SmartDiveBook/SmartDiveBook.db