I've looked through this question as well : problem about sqlite database, no such table: but have had no success in fixing the problem.
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
I was basically following this tutorial: http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
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.
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;
}
}
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);
}
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"