无法访问数据库

时间:2011-08-04 12:24:41

标签: android database sqlite

我正在(重新)编写一个使用SQLite数据库来存储各种项目的Android应用程序,此时我正在尝试打开数据库但是我收到以下logcat错误:

08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.os.Looper.loop(Looper.java:123)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.ActivityThread.main(ActivityThread.java:3691)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at java.lang.reflect.Method.invokeNative(Native Method)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at java.lang.reflect.Method.invoke(Method.java:507)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at dalvik.system.NativeStart.main(Native Method)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793): Caused by: android.database.sqlite.SQLiteException: unable to open database file
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1960)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:887)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at myApps.ShoppingList.Database.openDatabase(Database.java:83)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at myApps.ShoppingList.RoomList.onCreate(RoomList.java:25)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
08-04 13:05:52.735: ERROR/AndroidRuntime(7793):     ... 11 more

我目前的代码非常不完整,我只是在为它添加点点滴滴并尝试让它们正常运行,直到我得到的错误与丢失的代码有关。 (在我添加大量代码并迷失之前,确保应用程序中的代码有效)

我已经检查过我正在访问正确的路径并且数据库名称是正确的,我还试图让新的应用程序打开旧的数据库文件(它仍然在旧的应用程序中工作)但我得到了相同的logcat错误,所以我认为它与其他一些代码有关。我真的不确定从哪里开始。如果您需要更多信息或代码,我会根据要求发布。感谢您提供的任何帮助:)

以下是造成问题的两个类:

这是列表类,它最终将是数据库中所有项目的列表,并在列表项的右侧有一个复选框,当选中它时,它将从列表中删除该项目并将其放在不同的项目上列表(目前不重要)

public class RoomList extends ListActivity{
public String Room = MainMenu.room;
protected Database listdb;
MyAdapter adapterList;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.room);

    listdb = new Database(this, Room, null, 0);
    listdb.openDatabase();

    fillList();
}

private void fillList(){
    Cursor cursor = null;
    cursor = listdb.getRoom(Room);

    //not entirely sure how the managing cursor works, i think it just keeps everything synchronised
    startManagingCursor(cursor);

    //takes string values from the database, will eventually be displayed in the list views
    String [] names = new String []{Database.KEY_NAME, Database.KEY_SIZE, Database.KEY_BRAND, Database.KEY_TYPE, Database.KEY_DESCRIPTION};

    //sets what xml variables get modified with the taken strings
    int [] holder = new int []{R.id.additem, R.id.listDescription};

    //again not entirely sure how this method works, from what i can gather it basically defines which
    //layout to access when filing the xml variables in "holder" with the strings in "names"
    adapterList = new MyAdapter(RoomList.this, cursor);

            //seems to send whatever changes made with the last line of 
    //code to become a ListAdapter in order to be displayed as a list
}

private class MyAdapter extends ResourceCursorAdapter {

    public MyAdapter(Context context, Cursor cur) {
        super(context, R.layout.room, cur);
    }

    @Override
    public View newView(Context context, Cursor cur, ViewGroup parent) {
        LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        return li.inflate(R.layout.room, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cur) {
        TextView tvListText = (TextView)view.findViewById(R.id.listButton);
        CheckBox cbListCheck = (CheckBox)view.findViewById(R.id.checkbox1);

        tvListText.setText(cur.getString(cur.getColumnIndex(listdb.KEY_NAME)));
        cbListCheck.setChecked((cur.getInt(cur.getColumnIndex(listdb.KEY_ONLIST))==0? false:true));
    }
}
}

这是访问数据库的类:

public class Database extends SQLiteOpenHelper{

private static final String DATABASE_DIRECTORY = "data/data/myApps.ShoppingList/database/";
private static final String DATABASE_NAME = "listdb.sqlite";
private static final String DATABASE_PATH = DATABASE_DIRECTORY + DATABASE_NAME;
private static final String DATABASE_ITEMS_TABLE = "items";
private static final String DATABASE_CATEGORY_TABLE = "categorys";
public static final String KEY_NAME = "name";
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_BRAND = "brand";
public static final String KEY_SIZE = "size";
public static final String KEY_TYPE = "type";
public static final String KEY_ROOM = "room";
public static final String KEY_ONLIST = "onList";
public static final String KEY_ROWID = "_id";
static SQLiteDatabase listdb;
private Context m_context;

public Database(Context context, String name, CursorFactory factory, int version) {
    super(context, DATABASE_NAME, null, 1);
    m_context = context;
}

public void onCreate(SQLiteDatabase db) {}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}

public void createDatabase() throws IOException{
    boolean exists = checkDatabase();       
    if(!exists){
        this.getWritableDatabase();  
        try{
            copyDatabase();
        } catch(IOException e){
            throw new Error("Error copying database");
        }
    }
}

private boolean checkDatabase(){
    SQLiteDatabase check = null;        
    try{
        check = SQLiteDatabase.openDatabase(DATABASE_PATH, null, SQLiteDatabase.OPEN_READWRITE);
    } catch (SQLiteException e){}

    if(check != null){
        check.close();
        return true;
    }
    else return false;
}
private void copyDatabase() throws IOException{
    InputStream in = m_context.getAssets().open(DATABASE_NAME);
    OutputStream out = new FileOutputStream(DATABASE_PATH);
    byte[] buffer = new byte[1024];
    int length;

    while((length = in.read(buffer)) > 0){
        out.write(buffer, 0, length);
    }       
    out.flush();
    out.close();
    in.close();
}


public void openDatabase() throws SQLException{
    listdb = SQLiteDatabase.openDatabase(DATABASE_PATH, null, SQLiteDatabase.OPEN_READWRITE);
}

public synchronized void close(){
    if(listdb != null){
        listdb.close();
    }
    super.close();
}

public Cursor getRoom(String roomId){
    if (roomId=="1"){
        Cursor cursor = listdb.query(DATABASE_ITEMS_TABLE, new String[]{KEY_ROWID, KEY_NAME, KEY_BRAND, KEY_DESCRIPTION, KEY_SIZE, KEY_TYPE, KEY_ROOM, KEY_ONLIST},KEY_ROOM + " = 1 " + "AND " + KEY_ONLIST + " != 1 ", null, null, null, null, null);
        return cursor;
    }
    else if (roomId=="2"){
        Cursor cursor = listdb.query(DATABASE_ITEMS_TABLE, new String[]{KEY_ROWID, KEY_NAME, KEY_BRAND, KEY_DESCRIPTION, KEY_SIZE, KEY_TYPE, KEY_ROOM, KEY_ONLIST},KEY_ROOM + " = 2 " + "AND " + KEY_ONLIST + " != 1 ", null, null, null, null, null);
        return cursor;
    }
    else if (roomId=="3"){
        Cursor cursor = listdb.query(DATABASE_ITEMS_TABLE, new String[]{KEY_ROWID, KEY_NAME, KEY_BRAND, KEY_DESCRIPTION, KEY_SIZE, KEY_TYPE, KEY_ROOM, KEY_ONLIST},KEY_ROOM + " = 3 " + "AND " + KEY_ONLIST + " != 1 ", null, null, null, null, null);
        return cursor;
    }
    else if (roomId=="4"){
        Cursor cursor = listdb.query(DATABASE_ITEMS_TABLE, new String[]{KEY_ROWID, KEY_NAME, KEY_BRAND, KEY_DESCRIPTION, KEY_SIZE, KEY_TYPE, KEY_ROOM, KEY_ONLIST},KEY_ROOM + " = 4 " + "AND " + KEY_ONLIST + " != 1 ", null, null, null, null, null);
        return cursor;
    }
    else{
        Cursor cursor = listdb.query(DATABASE_ITEMS_TABLE, new String[]{KEY_ROWID, KEY_NAME, KEY_BRAND, KEY_DESCRIPTION, KEY_SIZE, KEY_TYPE, KEY_ROOM, KEY_ONLIST},KEY_ONLIST + "= 1" , null, null, null, null, null);
        return cursor;
    }
}
}

1 个答案:

答案 0 :(得分:1)

为什么使用SQLiteOpenHelper而不是使用SQLiteDatabase.open? 为什么要对数据库路径进行硬编码?

DATABASE_DIRECTORY = "data/data/myApps.ShoppingList/database/";

在许多设备上,我看到它实际上是...... / databases /,但无论如何,使用getDatabasePath来获取它。