Android Studio + SQLite,打开数据库时出错

时间:2014-06-04 13:32:47

标签: android database sqlite android-studio

我想使用Android Studio和SQLite编写一个简单的数据库。我将我的数据库放在src / main / assets / databases文件夹中,并检查app.iml中是否标记了assets-folder。它是。当我运行我的程序时,它会在此行崩溃

 Cursor friendCursor = database.query(TABLE_NAME, new String[] {FRIEND_ID,
            FRIEND_NAME}, null, null, null, null, FRIEND_NAME);

出现以下错误:

 android.database.sqlite.SQLiteException: no such table: Magic(code 1): , while compiling: SELECT _id, Name FROM Magic ORDER BY Name

我在某处读到,如果SQLite找不到数据库文件,它会创建一个空数据库,而这个新数据库没有“Magic”表。我想这就是发生的事情。 我是否必须将我的数据库文件放在其他地方?

我的程序有以下两个类:

MainActivity.java

package com.sqliteTests.sqlitetest3.app;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ListActivity {

private static final String DB_NAME = "MagicDatabase";

//A good practice is to define database field names as constants
private static final String TABLE_NAME = "Magic";
private static final String FRIEND_ID = "_id";
private static final String FRIEND_NAME = "Name";

private SQLiteDatabase database;
private ListView listView;
private ArrayList friends;

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


@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);
    //Our key helper
    ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(this, DB_NAME);
    database = dbOpenHelper.openDataBase();
    //That’s it, the database is open!
    fillFriends();
    setUpList();
    return true;
}
private void setUpList() {
    //We use a standard adapter and an element layout for brevity’s sake
    setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, friends));
    listView = getListView();

    //Let’s set a message shown upon tapping an item
    listView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView parent, View view,
                                int position,long id) {
            Toast.makeText(getApplicationContext(),
                    ((TextView) view).getText() +
                            " could be Softeq's friend",
                    Toast.LENGTH_SHORT).show();
        }
    }
    );
}

//Extracting elements from the database
private void fillFriends() {
    friends = new ArrayList<String>();
    Cursor friendCursor = database.query(TABLE_NAME, new String[] {FRIEND_ID,
            FRIEND_NAME}, null, null, null, null, FRIEND_NAME);
    friendCursor.moveToFirst();
    if(!friendCursor.isAfterLast()) {
        do {
            String name = friendCursor.getString(1);
            friends.add(name);
        } while (friendCursor.moveToNext());
    }
    friendCursor.close();
}



@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

ExternalDbOpenHelper.java

package com.sqliteTests.sqlitetest3.app;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class ExternalDbOpenHelper extends SQLiteOpenHelper {

//Path to the device folder with databases
public static String DB_PATH;

//Database file name
public static String DB_NAME;
public SQLiteDatabase database;
public final Context context;

public SQLiteDatabase getDb() {
    return database;
}

public ExternalDbOpenHelper(Context context, String databaseName) {
    super(context, databaseName, null, 1);
    this.context = context;
    //Write a full path to the databases of your application
    //String packageName = context.getPackageName();
    if(android.os.Build.VERSION.SDK_INT >= 4.2){
        DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
    }
    else
    {
        DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
    }
    DB_NAME = databaseName;
    openDataBase();
}

//This piece of code will create a database if it’s not yet created
public void createDataBase() {
    boolean dbExist = checkDataBase();
    if (!dbExist) {
        this.getReadableDatabase();
        try {
            copyDataBase();
        } catch (IOException e) {
            Log.e(this.getClass().toString(), "Copying error");
            throw new Error("Error copying database!");
        }
    } else {
        Log.i(this.getClass().toString(), "Database already exists");
    }
}

//Performing a database existence check
private boolean checkDataBase() {
    SQLiteDatabase checkDb = null;
    try {
        String path = DB_PATH + DB_NAME;
        checkDb = SQLiteDatabase.openDatabase(path, null,
                SQLiteDatabase.OPEN_READONLY);
    } catch (SQLException e) {
        Log.e(this.getClass().toString(), "Error while checking db");
    }
    //Android doesn’t like resource leaks, everything should
    // be closed
    if (checkDb != null) {
        checkDb.close();
    }
    return checkDb != null;
}

//Method for copying the database
private void copyDataBase() throws IOException {
    //Open a stream for reading from our ready-made database
    //The stream source is located in the assets
    InputStream externalDbStream = context.getAssets().open(DB_NAME);

    //Path to the created empty database on your Android device
    String outFileName = DB_PATH + DB_NAME;

    //Now create a stream for writing the database byte by byte
    OutputStream localDbStream = new FileOutputStream(outFileName);

    //Copying the database
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = externalDbStream.read(buffer)) > 0) {
        localDbStream.write(buffer, 0, bytesRead);
    }
    //Don’t forget to close the streams
    localDbStream.close();
    externalDbStream.close();
}

public SQLiteDatabase openDataBase() throws SQLException {
    String path = DB_PATH + DB_NAME;

    if (database == null) {
        createDataBase();
        database = SQLiteDatabase.openDatabase(path, null,
                SQLiteDatabase.OPEN_READWRITE);
    }
    return database;
}

@Override
public synchronized void close() {
    if (database != null) {
        database.close();
    }
    super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}

}

0 个答案:

没有答案