在 Android Eclipse Project 上的 assets 文件夹中拥有自己的数据库



我的安卓应用程序遇到了一个大问题。我是第一次开发带有sqlite数据库的Android应用程序,但我遇到了无法解决的问题。

我在日食项目的资产文件夹中有我的sqlite数据库,名为saldb.sqlite

我有以下类来管理具有单调模式的数据库:

package sal.app.logic;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteException;
    import android.database.sqlite.SQLiteOpenHelper;
    public class DataBaseManager extends SQLiteOpenHelper{
    private static DataBaseManager dbManagerInstance = null;
    private Context salContext;
    private  SQLiteDatabase salDatabase;
    private static  String DB_PATH = "/data/data/sal.app/databases/";
    private static String DB_NAME = "saldb.sqlite";

    private DataBaseManager(Context c)
    {
        super(c, DB_NAME, null, 1);
        //this.salContext = c;
    }
    public static DataBaseManager getSalDatabase(Context c)
    {
        if (dbManagerInstance == null)
        {
            dbManagerInstance = new DataBaseManager(c);
        }
        return dbManagerInstance;
    }
    public void createDataBase() throws IOException{
        boolean dbExist = checkDataBase();
        if(dbExist){
            //do nothing - database already exist
        }else{
            //By calling this method and empty database will be created into the default system path
            //of your application so we are gonna be able to overwrite that database with our database.
            this.getReadableDatabase();
            try {
                copyDataBase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    private boolean checkDataBase()
    {
        SQLiteDatabase checkDB = null;
        try{
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        }catch(SQLiteException e){
            //database does't exist yet.
        }
        if(checkDB != null){
            checkDB.close();
        }
        return checkDB != null ? true : false;
    }
    private void copyDataBase() throws IOException{
        //Open your local db as the input stream
        InputStream myInput = salContext.getAssets().open(DB_NAME);
        // Path to the just created empty db
        //String outFileName = DB_PATH + DB_NAME;
        String outFileName = "/data/data/sal.app/databases/saldb.sqlite";
        //Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(outFileName);
        //transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }
        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }
    public void openDataBase() throws SQLException{
        //Open the database
        String myPath = DB_PATH + DB_NAME;
        salDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }
    @Override
    public synchronized void close() {
            if(salDatabase != null)
                salDatabase.close();
            super.close();
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        //db.execSQL("Insert Into Question(_id,level,text,idTopic) Values (1,1,'asa',0)");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
        // Add your public helper methods to access and get content from the database.
       // You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
       // to you to create adapters for your views.
    public Question getOneQuestion()
    {
        //list of Versioni, search result with query text
                Question quest = new Question();
                try
                {
                    //open database to query
                    openDataBase();
                    //salDatabase.execSQL("Insert Into Question(_id,level,text,idTopic) Values (1,1,'asa',0)");
                    //Cursor cursor = salDatabase.rawQuery("SELECT text, idTopic, level from Question WHERE level=2", null);
                    Cursor cursor = salDatabase.rawQuery("SELECT * from Question", null);

                    /*Cursor cursor = salDatabase.query("Question",
                            new String[] { "text","idTopic","level"},
                            "level=2",
                            null ,
                            null,
                            null,
                            "RANDOM() LIMIT 1");*/
                    //Cursor c = db.rawQuery(select, null); */
                //mapped all rows to data object

                    if (cursor.moveToFirst())       
                    {
                        System.out.println(cursor.getString(2));
                        do
                        {
                            Cursor cursor2 = salDatabase.rawQuery("SELECT * from Topic WHERE _id=0", null);
                            cursor2.moveToFirst();
                            Topic t = new Topic(cursor2.getString(1));
                           quest = new Question(cursor.getString(2),t,(int)cursor.getShort(1));
                           break;
                        } while (cursor.moveToNext());
                    }   
                    //close cursor      
                    cursor.close();     
                }
                catch(Exception ex)
                {
                    System.out.println("DatabaseHelper.search()- : ex " + ex.getClass() +", "+ ex.getMessage());
                }
                //  
                return quest;
    }
    /*public ArrayList<Answer> getAnswersOfQuestion(Questin q)
    {
    }*/
}

但是在我第一次运行我的应用程序时,我有以下错误:

05-29 23:55:45.684:D/ddm堆(221):收到功能列表请求05-29 23:55:46.295: D/dalvikvm(221): GC 在 109ms 内释放了 519 个对象/45792 字节05-29 23:55:46.544: E/Database(221): sqlite3_open_v2("/data/data/sal.app/databases/saldb.sqlite", &handle, 1, NULL) 失败

05-29 23:55:46.594: D/Android运行时(221): 关闭虚拟机05-29 23:55:46.604:W/dalvikvm(221):threadid=3:线程退出,出现未捕获的异常(组=0x4001b188)

05-29 23:55:46.604: E/Android运行时(221): 未捕获的处理程序:由于未捕获的异常,线程主退出

在我的主要活动中,我这样做:

public class SALActivity extends Activity {
    Button back;
    Button choiceA;
    static int choice = 0;
    DataBaseManager db;
    //Button choiceB;
    //Button choiceC;
    //Button choiceD;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gamemenu);
        //db= new DataBaseManager(this);
        db=DataBaseManager.getSalDatabase(this);
        try {
            db.createDataBase();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //db=DataBaseManager.getSalDatabase(this);
        Question q = db.getOneQuestion();
        //back = (Button) findViewById(R.id.gaveup_button);
        choiceA = (Button) findViewById(R.id.choice_a_button);
        choiceA.setTextColor(0xffffffff);
        //choiceA.setText("A: Académica");
        choiceA.setText(q.getQuestionText());
        choiceA.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

            }
        });
        //choiceA.setText(10);
        //choiceB = (Button) findViewById(R.id.choice_b_button);
        //choiceC = (Button) findViewById(R.id.choice_c_button);
        //choiceD = (Button) findViewById(R.id.choice_d_button);
        //Intent v = new Intent(this, SALActivity.class);
        //this.startActivity(v);
    }
}

在我第二次运行应用程序时,不会发生错误,数据库位于正确的路径中,但只有表android_metadata

我也可以说,如果我将正确的数据库放在/data/data/sal.app/databases/上,整个程序就可以工作了......错误在复制数据库中。

这是我

复制数据库的工作代码。

private static String DB_PATH = "/data/data/com.demo.databaseDemo/databases/";
 private static String DB_NAME = "myDatabase.db";   
 private void copyDataBase() throws IOException{
            //Open your local db as the input stream
            InputStream myInput = _myContext.getAssets().open(DB_NAME);
            // Path to the just created empty db
            String outFileName = DB_PATH + DB_NAME;
            //Open the empty db as the output stream
            OutputStream myOutput = new FileOutputStream(outFileName);
            //transfer bytes from the inputfile to the outputfile
            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer))>0){
                myOutput.write(buffer, 0, length);
            }
            //Close the streams
            myOutput.flush();
            myOutput.close();
            myInput.close();
        }//end of copyDataBase() method

需要为数据库创建文件夹,并在应用首次运行时复制到该文件夹中。 这是我的工作:

    // Check to see if database exists, otherwise copy from assets
    boolean dbExist = db.databaseExist();
    if (!dbExist) {
        try {
            // See if there is a data directory, otherwise create it
            String destPath = "/data/data/" + getActivity().getPackageName() +
                    "/databases/";
            File f = new File(destPath);
            if (!f.exists()) {
                f.mkdirs();
                f.createNewFile();
                // Copy from assets to data directory
                CopyDB(getActivity().getBaseContext().getAssets().open("myData.sqlite"),
                        new FileOutputStream(destPath + "/myData.sqlite"));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }    
    }       

最新更新