我正在(重新)编写一个使用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;
}
}
}
答案 0 :(得分:1)
为什么使用SQLiteOpenHelper而不是使用SQLiteDatabase.open? 为什么要对数据库路径进行硬编码?
DATABASE_DIRECTORY = "data/data/myApps.ShoppingList/database/";
在许多设备上,我看到它实际上是...... / databases /,但无论如何,使用getDatabasePath来获取它。