Android设备上的SQLite异常:没有这样的表,但emulator工作正常吗?
我也仔细研究了这个问题: 但在解决问题方面没有成功 正如标题所提到的,完全相同的代码能够在emulator fine上运行(显示表),但在设备上发现“没有这样的表”时遇到异常。使用HTC Desire Z Android 2.2.1版 我基本上遵循了本教程: 其想法是将预加载的数据库复制到android应用程序将用于更改的目录,然后在调用save时复制到sd卡。然而,尽管从assets文件夹到app database目录的复制工作正常,到SD卡的复制工作正常(通过使用sqlite浏览器打开复制到SD卡的db文件进行测试),但尝试在设备上显示数据库给了我一个问题,而我在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浏览器打开复制到
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文件来保护布尔值以进行检查/
希望这对你有帮助
有很好的编码