在Android设备SQLite的例外:没有这样的表,但仿真器工作正常?仿真器、正常、设备、工作

2023-09-06 18:39:17 作者:與妳爲伴怎會膩

我已经通过了这个问题看起来还有:problem有关SQLite数据库,没有这样的表:但不得不在解决问题没有成功。

I've looked through this question as well : problem about sqlite database, no such table: but have had no success in fixing the problem.

正如标题所提到的,完全相同的code能够在模拟器上运行良好(显示表),但运行与没有这样的表在设备上发现了异常。使用HTC Desire Z的Andr​​oid版本2.2.1

As the title mentions, the exact same code was able to run on the emulator fine(displays the table) but runs into the exception with "no such table" found on the device. Using an HTC Desire Z Android version 2.2.1

我基本上是按照本教程:的http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/

I was basically following this tutorial: http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/

这个想法是到preloaded数据库复制到Android应用程序将使用更改,然后走上了一条拯救被称为拷贝到SD卡的目录。不过,虽然从资产文件夹拷贝到应用程序数据库目录工作正常,并拷贝到SD卡做工精细,试图显示数据库(通过打开复制到使用SQLite的浏览器SD卡中的数据库文件进行测试)在设备上给了我一个问题,而我已经在模拟器运行到没有问题的。

The idea being to copy a preloaded database to the directory which the android app will use to make changes to, then copy out to the sd card upon a save being called. However, although the copy from the assets folder to the app database directory works fine, and the copy to the SD card works fine (tested by opening the db file copied out to the sd card using an sqlite browser), trying to display the database on the device gives me a problem whereas i've run into no problems at all with the emulator.

这里是code数据库助手:

here is the code for the database helper:

 public class DatabaseHelper extends SQLiteOpenHelper{

private static String DB_PATH = "/data/data/com.mko.preloaddb/databases/";
private static String DB_NAME = "preloaddb";
private SQLiteDatabase myDB;
private final Context myContext;


public DatabaseHelper(Context context) {
    super(context, DB_NAME, null, 1);
    this.myContext = context;
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // TODO Auto-generated method stub

}

/**
 * Creates DB by copying over DB from assets if it doesn't exist yet
 * @throws IOException
 */
public void createDatabase() throws IOException{
    boolean dbExist = checkDatabase();

    if(dbExist){
        Log.e("DatabaseHelper","database exists");
    }else{
        this.getReadableDatabase().close();

        try{
            //copy preloaded db from assets if it doesn't exist yet
            copyDatabase();
        }catch(IOException e){
            throw new Error("Error copying database");
        }
    }
}

public void openDatabase() throws SQLException{
    //open the database
    String myPath = DB_PATH + DB_NAME;
    myDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}

/***
 * Copies preloaded db from assets
 * @throws IOException
 */
private void copyDatabase() throws IOException{
    //Open local db as input steam
    InputStream myInput = myContext.getAssets().open(DB_NAME);

    //Path to just created empty db
    String outFileName = DB_PATH + DB_NAME;

    //open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    byte[] buffer = new byte[1024];
    int length;
    while((length = myInput.read(buffer))>0){
        myOutput.write(buffer,0,length);
    }

    myOutput.flush();
    myOutput.close();
    myInput.close();


}

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 doesn't exist yet, so checkDB will be null
    }
    if(checkDB !=null){
        checkDB.close();            
    }
    return checkDB !=null ? true : false;
    }

}

这里是code为调用它的活动:

And here is the code for the activity that calls it:

public class PreloadDBTestActivity extends Activity {
/** Called when the activity is first created. */
Application myApp;
DatabaseHelper myDbHelper;
SQLiteDatabase myDb;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    myApp = this.getApplication();
    myDbHelper = new DatabaseHelper(this);               
    setContentView(R.layout.main);

}

public void refreshViewTable(View v){

    TableLayout tl = (TableLayout)findViewById(R.id.tbl_dbview);
    if(myDb==null || !myDb.isOpen()){
        openDB(null);
    }
    String[] result_columns = new String[]{"_id","baseclassname","basehealth"};
    Cursor allRows = myDb.query(true, "baseclasses", result_columns, null, null, null, null, null, null);

    if(allRows.moveToFirst()){
        do{
            String classname = allRows.getString(1);
            TableRow curr = new TableRow(this);
            TextView text = new TextView(this);
            text.setText(classname);
            curr.addView(text);
            tl.addView(curr);
        }while(allRows.moveToNext());
    }


}

public void openDB(View v){
    TextView tv = (TextView)findViewById(R.id.lbl_debug);
    try{
        myDbHelper.createDatabase();
    }catch (IOException ioe){
        throw new Error("Unable to create database");
    }
    try{
        myDb = myDbHelper.getWritableDatabase();
    }catch(SQLiteException e){

        tv.setText("Unable to open writable database");
    }
    Toast.makeText(this, "Successful open, copy should work", Toast.LENGTH_LONG).show();

}

public boolean copyDbToSd(View v){
    File dbfile = new File(Environment.getDataDirectory()+"/data/com.mko.preloaddb/databases/preloaddb");
    File exportDir = new File(Environment.getExternalStorageDirectory(),"/exampledata/example");

    TextView tv = (TextView)findViewById(R.id.lbl_debug);
    if(myDb.isOpen()){
        myDb.close();

    }

    if(!exportDir.exists()){
        boolean success = exportDir.mkdirs();

        tv.setText("Making dir");
        if(success){
            Toast.makeText(this, "Success expor dir !"+exportDir.getAbsolutePath(), Toast.LENGTH_LONG).show();

        }else{
            Toast.makeText(this, "No success expor dir =("+exportDir.getAbsolutePath(), Toast.LENGTH_LONG).show();
        }

    }
    if(!dbfile.exists()){           
        tv.setText("Database file does not exist or wrong directory "+dbfile.getAbsolutePath());
    }else{          
        tv.setText("Database file found! " +dbfile.getAbsolutePath());
    }
    File file = new File(exportDir,dbfile.getName());
    try{
        file.createNewFile();
        if(!file.exists()){
            Toast.makeText(this, "DestinationFile does not exist!", Toast.LENGTH_LONG).show();
        }
        this.copyfile(dbfile, file);
        return true;            
    }catch (IOException e){
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
        Log.e("Preload", e.getMessage(), e);
        return false;
    }
}

private void copyfile(File src, File dst) throws IOException{
    FileChannel inChannel = new FileInputStream(src).getChannel();
    FileChannel outChannel = new FileOutputStream(dst).getChannel();
    try{
        inChannel.transferTo(0, inChannel.size(), outChannel);
    }finally{
        if(inChannel!=null){
            inChannel.close();
        }           
        if(outChannel!=null){
            outChannel.close();
        }
    }
}

private boolean isExternalStorageAvail(){
    return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);     
}

以防万一它的混乱,我已经绑定的方法openDB,copyDbToSd和refreshViewTable,以在GUI上的按钮,和我打的按钮中的openDB的顺序,refreshViewTable和 copyDBToSd

Just in case it's confusing, i've bound the methods "openDB","copyDbToSd" and "refreshViewTable" to buttons on the gui, and I hit the buttons in the order of "openDB", "refreshViewTable" and "copyDBToSd"

推荐答案

我已经与方法相同的问题。

I've already had the same problem with the method

SQLiteDatabase.openDatabase

方法getWritebleDatabase()调用DBHandler(如果数据库文件不存在,那么的OnOpen())。

the method getWritebleDatabase() calls the onCreate() method of the DBHandler (if DB file doesn't exists, then onOpen() ).

所以,也许你可以看看下面的code:

So, maybe you can take a look at the code below:

公共类SqlDBAdapter {

public class SqlDBAdapter {

private static final String DB_NAME = "projHours.sqlite";
private static final int DB_VERSION = 1;

private static Context c;
private SQLiteDatabase db;
private SQLiteOpenHelper sqlDBHelp;

/**
 * Constructor for the SQL DB Adapter, copy DB from assets if not exists in /data/data/<package-name>/databases
 * 
 * @param c
 */
public SqlDBAdapter(Context c) {
    super();
    SqlDBAdapter.c = c;
    sqlDBHelp = new SqlDBHelper();
}

/**
 * Open the SQL DB as Writable
 */
public void openDB() {
    try {
        db = sqlDBHelp.getWritableDatabase();
    } catch (SQLiteException ex) {
        Toast.makeText(c, "DB with filename " + DB_NAME + "coudn't be opend!", Toast.LENGTH_SHORT);
    }
}

/**
 * Close the SQL DB
 */
public void closeDB() {
    db.close();
}

/**
 * Helper class for the SQL DB Adapter
 */
static class SqlDBHelper extends SQLiteOpenHelper {

    private static final String DB_PATH = "/data/data/" + c.getPackageName() + "/databases/" + DB_NAME;

    public SqlDBHelper() {
        super(c, DB_NAME, null, DB_VERSION);
        createDB();     
    }

    private void createDB() {

        SharedPreferences prefs = c.getSharedPreferences("sharedPrefs", 0);
        boolean dbExists = prefs.getBoolean("dbExists", false);
        Log.d("PM.ADA.SDA", "DB Exists : " + dbExists);
        if (!dbExists) {
            this.getReadableDatabase();
            copyDB();
            prefs.edit().putBoolean("dbExists", true).commit();
        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {}

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

    public void copyDB() {
        try {               
            InputStream is = c.getAssets().open(DB_NAME);
            BufferedInputStream bis = new BufferedInputStream(is);
            OutputStream os = new FileOutputStream(DB_PATH);
            BufferedOutputStream bos = new BufferedOutputStream(os);

            byte[] buffer = new byte[64];
            int length;

            while ((length = bis.read(buffer)) > 0) {
                bos.write(buffer, 0, length);
            }

            bos.flush();
            bos.close();
            bis.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

}

我使用一个内部类,它扩展了SQLiteOpenHelper我的数据库助手。这些方法的onCreate()和onUpgrade()在这里需要。

I use an inner class for my DB Helper that extends the SQLiteOpenHelper. the methods onCreate() and onUpgrade() are here required.

我使用一个共享的preferences文件安全的一个布尔值来检查,如果数据库存在于/数据/数据​​/

希望这会帮助你的!

I use a SharedPreferences file to safe a boolean value to check, if the database exists in /data/data/

Hope this will help you!

有很好的编码!