在Android Eclipse项目的Assets文件夹中拥有自己的数据库

时间:2012-05-30 00:02:50

标签: java android database sqlite

我的Android应用程序中存在很大问题。我是第一次使用sqlite数据库开发一个android应用程序,但我遇到了无法解决的问题。

我的sqlite数据库位于eclipse项目的assets文件夹中,名称为saldb.sqlite

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

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-heap(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”,&amp; handle,1,NULL)失败

05-29 23:55:46.594:D / AndroidRuntime(221):关闭VM 05-29 23:55:46.604:W / dalvikvm(221):threadid = 3:线程退出未捕获异常(组= 0x4001b188)

05-29 23:55:46.604:E / AndroidRuntime(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);
    }
}

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

我也可以说,如果我在/data/data/sal.app/databases/上放置正确的数据库,整个程序就可以正常工作...... 错误发生在copyDatabase中。

2 个答案:

答案 0 :(得分:1)

这是我复制数据库的工作代码。

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

答案 1 :(得分:0)

您需要为您的数据库创建文件夹,并在第一次运行应用程序时将其复制到该文件夹​​中。这是我的工作:

    // 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();
        }    
    }