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

iszxjhcz  于 2023-03-03  发布在  SQLite
关注(0)|答案(2)|浏览(572)

我正在使用下面的代码来打开或创建一个sqlite数据库。该代码在一些手机上工作正常,但在Android P设备上却会出现下面的错误。

SQLiteDatabase myDB = null;
myDB = backup.this.openOrCreateDatabase(url[0], MODE_PRIVATE, null);

对数表

2019-11-14 07:49:56.204 10213-10363/com.gadha.garden E/SQLiteLog: (14) cannot open file at line 36667 of [c255889bd9]
2019-11-14 07:49:56.204 10213-10363/com.gadha.garden E/SQLiteLog: (14) os_unix.c:36667: (2) open(/sdcard/Download/2019-11-14 07-49-56 AM.db) - 
2019-11-14 07:49:56.241 10213-10363/com.gadha.garden E/SQLiteDatabase: Failed to open database '/sdcard/Download/2019-11-14 07-49-56 AM.db'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
        at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:211)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:195)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:503)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:204)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:196)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:880)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:865)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:766)
        at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:772)
        at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:757)
        at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:306)
        at com.gadha.garden.backup$backupRestore.doInBackground(backup.java:120)
        at com.gadha.garden.backup$backupRestore.doInBackground(backup.java:108)
        at android.os.AsyncTask$2.call(AsyncTask.java:333)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
gcuhipw9

gcuhipw91#

考虑到你的评论
我正在尝试创建数据库。如何在创建数据库之前使用disableWriteAheadLogging?-
那么我相信你的问题是,你没有授予所需的权限,即使你说你有按照:-
添加了读和写权限。
您需要授予WRITE_EXTERNAL_STORAGE(这将隐式授予READ_EXTERNAL_STORAGE)。
对于设备API 23 + Android 6+而非9+,这需要通过MANIFEST授予权限,例如:-

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    • 但用户也必须按照**权限批准授予访问权限。对于API 23以下的设备,仅需要清单权限。

示例

下面是一个简单的示例,boh复制了该问题,并显示授予权限可以纠正该问题。

  • 清单包含上述uses-permission条目。

通过以下方式请求用户权限(ExternalStoragePermissions.java):-

abstract class ExternalStoragePermissions {

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    public ExternalStoragePermissions(Activity callingActivity) {}
    // Note call this method
    public static void verifyStoragePermissions(Activity activity) {
        int permission = ActivityCompat.checkSelfPermission(
                activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if(permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    activity,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }
    }
}

使用的活动(MainActivity.java)为:-

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Build.VERSION.SDK_INT >= 23) {
            ExternalStoragePermissions.verifyStoragePermissions(this);
        }

        SQLiteDatabase myDB = null;
        myDB = this.openOrCreateDatabase("/sdcard/Download/2019-11-14 07-49-56 AM.db", MODE_PRIVATE, null);
        DatabaseUtils.dumpCursor(
                myDB.query("sqlite_master",null,null,null,null,null,null)
        );
        myDB.close();
    }
}

结果编号
首次运行时,应用程序显示:-

    • 但是**由于主线程继续且未授予访问权限,因此日志包括:-
2019-11-15 08:35:33.439 11874-11874/a.so58855993copyfromassets D/AndroidRuntime: Shutting down VM
2019-11-15 08:35:33.440 11874-11874/a.so58855993copyfromassets E/AndroidRuntime: FATAL EXCEPTION: main
    Process: a.so58855993copyfromassets, PID: 11874
    java.lang.RuntimeException: Unable to start activity ComponentInfo{a.so58855993copyfromassets/a.so58855993copyfromassets.MainActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
        at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:197)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:505)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:198)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:915)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:895)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:786)
        at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:812)
        at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:797)
        at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:310)
        at a.so58855993copyfromassets.MainActivity.onCreate(MainActivity.java:27)
        at android.app.Activity.performCreate(Activity.java:7802)
        at android.app.Activity.performCreate(Activity.java:7791)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
    • 但是,在此阶段,应用程序仍处于活动状态,因为请求权限的对话框仍处于活动状态。单击允许**会导致应用程序崩溃,但随后会重新启动,并根据包含以下内容的日志成功创建数据库:-
2019-11-15 08:41:13.615 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@5df21a1
2019-11-15 08:41:13.616 I/System.out: 0 {
2019-11-15 08:41:13.616 I/System.out:    type=table
2019-11-15 08:41:13.616 I/System.out:    name=android_metadata
2019-11-15 08:41:13.616 I/System.out:    tbl_name=android_metadata
2019-11-15 08:41:13.616 I/System.out:    rootpage=3
2019-11-15 08:41:13.616 I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
2019-11-15 08:41:13.616 I/System.out: }
2019-11-15 08:41:13.616 I/System.out: <<<<<
  • 注意以上只是一个演示。在要使用的应用程序中,您显然需要在尝试访问数据库之前设置权限。
  • 理想情况下,您不应该硬编码路径,而是使用系统值,例如,Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)作为路径。
  • 通常,您会通过Context的getDatabasePath方法将数据库放置在应用程序的数据中,而不是将数据集放置在下载文件夹中。
  • 已授予对应用程序数据中标准位置的权限,因此无需请求。
thtygnil

thtygnil2#

如果这对正在阅读本文的人无效,请确保您的数据库规则允许访问。检查“使用”选项卡,查看是否有访问数据库的失败尝试。

相关问题