6

Edit: I tried this on my phone and it works, can anyone tell me why it does not work on an emulator?

I am trying to open a database on android, but it is throwing an "Database file could not be opened" Exception. In the debugger, it seems that the error is occurring on the line mDb = mDbHelper.getWritableDatabase();

My code is as follows:

package com.track.map;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


    public class DBAdapter {

        protected static final String DATABASE_NAME = "data";
        protected static final int DATABASE_VERSION = 1;

        //database tables
        //track table
        protected static final String TRACK_TABLE = "tracks";
        protected static final String TRACK_ID = "_id";
        protected static final String TRACK_DATE_TIME_START = "date_time_start";
        protected static final String TRACK_DATE_TIME_END = "date_time_end";

        //tables create
        protected static final String TRACK_TABLE_CREATE = 
                                "create table " + TRACK_TABLE + " ("
                                    + TRACK_ID + " integet promary key not null, "
                                    + TRACK_DATE_TIME_START + " text not null, "
                                    + TRACK_DATE_TIME_END + " text not null);";

        protected DatabaseHelper mDbHelper;
        protected SQLiteDatabase mDb;

        protected final Context mContext;

        public DBAdapter(Context context) {
            mContext = context;
        }

        public DBAdapter open() throws android.database.SQLException {
            mDbHelper = new DatabaseHelper(mContext);
            mDb = mDbHelper.getWritableDatabase();
            return this;
        }

        public void close() {
            mDb.close();
        }

        protected static class DatabaseHelper extends SQLiteOpenHelper {

            public DatabaseHelper(Context context) {
                super(context, DATABASE_NAME, null, DATABASE_VERSION);
            }

            @Override
            public void onCreate(SQLiteDatabase db) {
                db.execSQL(TRACK_TABLE_CREATE);
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                onCreate(db); //for now just recreate the database
            }

        }

    }

and

package com.track.map;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    private DBAdapter db;

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

        db = new DBAdapter(this);
        db.open();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

Does anyone know what the problem is?

EDIT:

The logcat is:

03-24 11:43:42.022: I/Database(758): sqlite returned: error code = 14, msg = cannot open file at source line 25467
03-24 11:43:42.022: E/Database(758): sqlite3_open_v2("/data/data/com.track.map/databases/data", &handle, 6, NULL) failed
03-24 11:43:42.032: D/AndroidRuntime(758): Shutting down VM
03-24 11:43:42.032: W/dalvikvm(758): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
03-24 11:43:42.062: E/AndroidRuntime(758): FATAL EXCEPTION: main
03-24 11:43:42.062: E/AndroidRuntime(758): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.track.map/com.track.map.MainActivity}: android.database.sqlite.SQLiteException: unable to open database file
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.os.Handler.dispatchMessage(Handler.java:99)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.os.Looper.loop(Looper.java:123)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ActivityThread.main(ActivityThread.java:4627)
03-24 11:43:42.062: E/AndroidRuntime(758):  at java.lang.reflect.Method.invokeNative(Native Method)
03-24 11:43:42.062: E/AndroidRuntime(758):  at java.lang.reflect.Method.invoke(Method.java:521)
03-24 11:43:42.062: E/AndroidRuntime(758):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
03-24 11:43:42.062: E/AndroidRuntime(758):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
03-24 11:43:42.062: E/AndroidRuntime(758):  at dalvik.system.NativeStart.main(Native Method)
03-24 11:43:42.062: E/AndroidRuntime(758): Caused by: android.database.sqlite.SQLiteException: unable to open database file
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1812)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
03-24 11:43:42.062: E/AndroidRuntime(758):  at com.track.map.DBAdapter.open(DBAdapter.java:37)
03-24 11:43:42.062: E/AndroidRuntime(758):  at com.track.map.MainActivity.onCreate(MainActivity.java:17)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
03-24 11:43:42.062: E/AndroidRuntime(758):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
03-24 11:43:42.062: E/AndroidRuntime(758):  ... 11 more
4

5 回答 5

5

这可能有点晚了,但希望这对遇到这个问题的人有所帮助(因为我找不到明确的解决方案)。

我想我知道这个原因的原因(至少就我而言)。查看DDMS --> File Explorer,您会发现数据库文件夹 ( /data/data//databases/) 不存在,这就是应用程序无法在该不存在的文件夹中创建数据库文件的原因。如果您可以通过某种方式创建数据库文件夹,则可以避免此问题。

因为我很懒,所以/data/data//files/我在模拟器模式下只使用了该文件夹。您可以使用以下方法获取文件目录:

context.getFilesDir().getPath()

这在模拟器中对我来说非常有用。

希望这可以帮助某人。

如果您想查看一些代码:

String dbFilename = "example.db";
try
{       
    File databaseFile = getDatabasePath(dbFilename);        
    SQLiteDatabase _db = SQLiteDatabase.openOrCreateDatabase(databaseFile);
} catch (Exception e)
{
    String databasePath =  getFilesDir().getPath() +  "/" + dbFilename;
    File databaseFile = new File(databasePath); 
    _db = SQLiteDatabase.openOrCreateDatabase(databaseFile);
}

编辑:

我尝试在模拟器上登录 Facebook(我的应用程序具有 FB 集成),然后 /databases 文件夹出现(并持续存在)。不知道发生了什么,但有可能以某种方式创建该文件夹。这里有另一位专家可以阐明的东西。

于 2013-08-29T12:49:14.227 回答
2

在你的构造函数上试试这个

public youeConstructor(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        context.openOrCreateDatabase(DATABASE_NAME, context.MODE_PRIVATE, null);
    }
于 2014-12-01T11:09:39.513 回答
1

我一直在寻找解决这个问题的方法,但没有找到任何可行的方法......但幸运的是我做了一些解决它的方法。这就是我所做的:

打开您的 adb shell 并删除您尝试打开的数据库。对于不知道如何使用 Linux 终端的人:

// 首先从命令行打开 adb shell

adb shell

// 然后这些是您需要的命令(更改您的应用程序包的 YOUR.APP.PACKAGE,它应该看起来像 com.domain.apilcation )

cd /data/data/YOUR.APP.PACKAGE/databases/
ls

最后一个命令 (ls) 将列出您为项目创建的所有数据库,现在您可以删除无法打开的数据库。首先,您应该复制它,以免丢失任何重要数据。(我假设您的数据库名为 your_database.db)

cp your_database.db your_database.db_backup
rm your_database.db

然后你应该启动你的应用程序,它应该创建一个新的数据库,对我来说这永久地解决了这个问题。

我希望这有帮助!

于 2014-03-30T12:05:41.183 回答
1

尽管与您当前的问题无关,但 SQLiteOpenHelper 中的 onUpgrade 方法将来也必然会失败:如果您在部署新版本的数据库时要执行的操作是从头开始,则需要删除首先是旧表。

编辑经过一些研究,我发现您的问题相当普遍:

Android SQLiteOpenHelper 无法打开数据库文件

此答案提供的 3 个链接

https://stackoverflow.com/a/8957994/2177061

如果您找不到使错误消失的干净方法,则特别有趣并提供某种解决方法。

这就是说,如果我在你那里,作为在深入研究复杂的解决方法之前第一次尝试解决你的问题,我会尝试更新所有 Android 开发工具(特别是 SDK,但更新 eclipse 插件不会受到伤害),完全删除来自模拟器和设备的应用程序,然后再次运行它。

祝你好运!

编辑 2忽略以下备注(不正确,留在这里供参考)

您的代码不起作用,因为 SQL 查询错误:您拼写了

integet promary

它应该在哪里

integer primary

(此外,我也碰巧对 Android db 类感到疯狂,只是发现问题出在 SQL 查询中:))

希望这可以帮助

于 2013-03-24T10:22:21.097 回答
0
Why are you keeping code complex try this


public SQLiteDatabase sampleDB;
    public String COLUMN_ID="_id";
    public String COLUMN1="username";
    public String COLUMN2="password";
    public String TABLE_NAME="Androdata";

sampleDB =  this.openOrCreateDatabase(TABLE_NAME, MODE_PRIVATE, null);

private void insertDB() {
        sampleDB.execSQL("INSERT INTO " +
                TABLE_NAME +
                " Values ('1','Androviewer','viewer');");   
        System.out.println("Inserted data successfully....");
    }
    private void createDB() {
        sampleDB.execSQL("CREATE TABLE IF NOT EXISTS " +
                TABLE_NAME+ "(" + COLUMN_ID
                + " integer primary key autoincrement, " + COLUMN1
                + " text not null,"+ COLUMN2
                + " text not null);");
        System.out.println("Database created successfully....");
    }
于 2013-03-24T10:06:42.257 回答