Android设备上的SQLite异常:没有这样的表,但emulator工作正常吗?

Android设备上的SQLite异常:没有这样的表,但emulator工作正常吗?,sqlite,exception,android-emulator,android,Sqlite,Exception,Android Emulator,Android,我也仔细研究了这个问题: 但在解决问题方面没有成功 正如标题所提到的,完全相同的代码能够在emulator fine上运行(显示表),但在设备上发现“没有这样的表”时遇到异常。使用HTC Desire Z Android 2.2.1版 我基本上遵循了本教程: 其想法是将预加载的数据库复制到android应用程序将用于更改的目录,然后在调用save时复制到sd卡。然而,尽管从assets文件夹到app database目录的复制工作正常,到SD卡的复制工作正常(通过使用sqlite浏览器打开复制到

我也仔细研究了这个问题: 但在解决问题方面没有成功

正如标题所提到的,完全相同的代码能够在emulator fine上运行(显示表),但在设备上发现“没有这样的表”时遇到异常。使用HTC Desire Z Android 2.2.1版

我基本上遵循了本教程:

其想法是将预加载的数据库复制到android应用程序将用于更改的目录,然后在调用save时复制到sd卡。然而,尽管从assets文件夹到app database目录的复制工作正常,到SD卡的复制工作正常(通过使用sqlite浏览器打开复制到SD卡的db文件进行测试),但尝试在设备上显示数据库给了我一个问题,而我在emulator上没有遇到任何问题

以下是数据库帮助器的代码:

 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;
    }

}
下面是调用它的活动的代码:

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”的顺序点击按钮。

我已经遇到了与该方法相同的问题

SQLiteDatabase.openDatabase

getWriteBledDatabase()方法调用DBHandler的onCreate()方法(如果DB文件不存在,则调用onOpen()

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

公共类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();
        }
    }

}
私有静态最终字符串DB_NAME=“projHours.sqlite”; 私有静态最终int DB_版本=1; 私有静态上下文c; 专用数据库数据库; 私有SQLiteOpenHelper sqlDBHelp; /** *SQL DB适配器的构造函数,如果/data/data//数据库中不存在数据库,则从资产复制DB * *@param c */ 公共SqlDBAdapter(上下文c){ 超级(); SqlDBAdapter.c=c; sqlDBHelp=newsqldbhelper(); } /** *以可写方式打开SQL数据库 */ public void openDB(){ 试一试{ db=sqlDBHelp.getWritableDatabase(); }catch(SQLiteException-ex){ Toast.makeText(c,“文件名为“+DB\u NAME+”不能打开的DB!”,Toast.LENGTH\u SHORT); } } /** *关闭SQL数据库 */ 公共数据库(){ db.close(); } /** *SQL DB适配器的帮助器类 */ 静态类SqlDBHelper扩展了SQLiteOpenHelper{ 私有静态最终字符串DB_PATH=“/data/data/”+c.getPackageName()+”/databases/“+DB_NAME; 公共SqlDBHelper(){ super(c,DB_名称,null,DB_版本); createDB(); } 私有void createDB(){ SharedReferences prefs=c.getSharedReferences(“SharedReferences”,0); boolean dbExists=prefs.getBoolean(“dbExists”,false); Log.d(“PM.ADA.SDA”,“数据库存在:”+dbExists); 如果(!dbExists){ 这是.getReadableDatabase(); copyDB(); prefs.edit().putBoolean(“dbExists”,true.commit(); } } @凌驾 public void onCreate(SQLiteDatabase db){} @凌驾 public void onUpgrade(SQLiteDatabase db,intoldversion,intnewversion){} public void copyDB(){ 试试{ InputStream is=c.getAssets().open(DB_NAME); BufferedInputStream bis=新的BufferedInputStream(is); OutputStream os=新文件OutputStream(DB_路径); BufferedOutputStream bos=新的BufferedOutputStream(os); 字节[]缓冲区=新字节[64]; 整数长度; 而((长度=双读(缓冲区))>0){ 写入(缓冲区,0,长度); } bos.flush(); bos.close(); 二、关闭(); }捕获(IOE异常){ e、 printStackTrace(); } } }
}

我为我的DB Helper使用了一个内部类,它扩展了SQLiteOpenHelper。这里需要onCreate()和onUpgrade()方法

如果数据库存在于/data/data中,我使用SharedReferences文件来保护布尔值以进行检查/ 希望这对你有帮助

有很好的编码