编辑: 我在手机上尝试了这个并且它有效,有人能告诉我为什么它在模拟器上不起作用吗?
我正在尝试在android上打开一个数据库,但它正在抛出“数据库文件无法打开”的例外情况。在调试器中,似乎错误发生在行mDb = mDbHelper.getWritableDatabase();
我的代码如下:
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
}
}
}
和
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;
}
}
有谁知道问题是什么?
编辑:
logcat是:
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
答案 0 :(得分:5)
这可能有点晚了,但希望这有助于谁遇到这个问题(因为我无法找到明确的解决方案)。
我想我知道这个原因的原因(至少在我的情况下)。查看 DDMS - &gt; 文件资源管理器,您意识到数据库文件夹(/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集成),之后出现(并保留)。不确定发生了什么,但有可能以某种方式创建该文件夹。在这里为另一位专家提供了解决方案。
答案 1 :(得分:1)
尽管与当前问题无关,但SQLiteOpenHelper中的onUpgrade方法在将来也必然会失败:如果在部署新版本的db时要采取的操作是从头开始,那么需要先删除旧表。
编辑经过一番研究后,我发现您的问题很常见:
Android SQLiteOpenHelper cannot open database file
此答案提供的3个链接
https://stackoverflow.com/a/8957994/2177061
特别有趣,并提供某种解决方法,如果你找不到一个干净的方法让bug消失。
如果我在你身边,作为第一次尝试解决你的问题,然后再尝试复杂的解决方法,我会尝试更新所有Android开发工具(特别是SDK,但更新eclipse插件不会受到伤害) ,从模拟器和设备中完全删除您的应用程序,然后再次运行它。
祝你好运!编辑2 忽略以下注释(不正确,我将此处留待参考)
您的代码不起作用,因为SQL查询错误:您拼写
integet promary
应该在哪里
integer primary
(此外,我也遇到过这样的问题,我对Android数据库类感到疯狂,却发现问题存在于SQL查询中:))
希望这有帮助
答案 2 :(得分:1)
在构造函数上尝试这个
public youeConstructor(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
context.openOrCreateDatabase(DATABASE_NAME, context.MODE_PRIVATE, null);
}
答案 3 :(得分: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....");
}
答案 4 :(得分:0)
我一直在寻找这个问题的解决方案,我找不到任何有用的东西......但幸运的是我做了一些解决它的事情。这就是我所做的:
打开您的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
然后你应该启动你的应用程序,它应该创建一个新的数据库,对我来说这永远解决了这个问题。
我希望这有帮助!