1

I am using some code that will copy an existing SQLite database from my assets folder into my /data/data/package folder. I have written the code and tested it on the android emulator, and it works fine. If I try and install it on my device (HTC Desire)I get 'SQLiteException:unable to open database file'

I have been stuck on this for 3 days now and cannot figure out what is going wrong. I don't know if the database cannot be opened because it is not created, or if I am lacking some database permissions in the manifest file. This is my DataBaseHelper code:

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.SQLiteOpenHelper;
import android.os.Environment;
import android.util.Log;

public class DataBaseHelper extends SQLiteOpenHelper{
    //private static String DB_PATH = "/data/data/com.drager/databases/";
    private static String DB_PATH = Environment.getDataDirectory()+"/data/com.drager/databases/";
    final static String DB_NAME = "myDBName";
    private SQLiteDatabase myDataBase=null;
    private final Context myContext;
    private DataBaseHelper myDbHelper;
    private static String TAG ="MyActivity";

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

    }

    public DataBaseHelper createDataBase() throws IOException{
        boolean dbExist =checkDataBase();
        //SQLiteDatabase db_read =null;
        Log.i(TAG,"############value of dbExist"+dbExist+"##########");
        //if (dbExist){
            //db must exist
        //}
        //else{
        //myDbHelper = new DataBaseHelper(myContext);
        //myDataBase = myDbHelper.getReadableDatabase();
        //myDataBase.close();
        //this.getReadableDatabase();
            //db_read.close();

        //    try {
                copyDataBase();
        //  } catch (IOException e) {
        //      throw new Error("error copying database");
        //  }
    //  }
        return this;

    }

    public Cursor executeStatement(){
        Log.i(TAG,"in execute statement");
        Cursor cursor=null;

        cursor=myDataBase.rawQuery("SELECT _ID, title, value "+
                    "FROM constants ORDER BY title",
                     null);
        return cursor;
    }

    public String getTextViewItem(){

        Cursor cursor=null;

        String str="";
        //store query results in cursor
        cursor=myDataBase.rawQuery("SELECT description FROM product_details" ,
                     null);
        cursor.moveToNext();
        //cast cursor content from the index of 'description Column as a string
        str =cursor.getString(cursor.getColumnIndex("description"));

        return str;
    }

    public void copyDataBase() throws IOException{
        // open db as input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        //path to newly created db
        String outFileName =DB_PATH + DB_NAME;

        //open empty db as 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);
        }

        myOutPut.flush();
        myOutPut.close();
        myInput.close();


    }

    private boolean checkDataBase() {
        SQLiteDatabase checkDB = null;

        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
        /*
        if (checkDB != null){
            checkDB.close();
        }*/
        return checkDB !=null ? true : false;
    }

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

    @Override
    public synchronized void close(){
        if(myDataBase != null){
            myDataBase.close();
        }
        super.close();
    }

    @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

    }

}

This is my manifest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.drager"
 android:versionCode="1"
 android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/

app_name" android:debuggable="true">
  <activity android:name=".Drager"
             android:label="Drager">
<intent-filter>
           <action android:name="android.intent.action.MAIN" />
           <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

This is the Logcat

02-09 09:09:15.883: ERROR/AndroidRuntime(8313):
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.drager/com.drager.Drager}:
android.database.sqlite.SQLiteException: unable to open database file
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:
2787)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:
2803)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.ActivityThread.access$2300(ActivityThread.java:135)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.os.Handler.dispatchMessage(Handler.java:99)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.os.Looper.loop(Looper.java:144)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.ActivityThread.main(ActivityThread.java:4937)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
java.lang.reflect.Method.invokeNative(Native Method)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
java.lang.reflect.Method.invoke(Method.java:521)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
dalvik.system.NativeStart.main(Native Method)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313): Caused by:
android.database.sqlite.SQLiteException: unable to open database file
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:
1902)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:
884)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
com.drager.DataBaseHelper.checkDataBase(DataBaseHelper.java:108)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
com.drager.DataBaseHelper.createDataBase(DataBaseHelper.java:32)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
com.drager.Drager.onCreate(Drager.java:46)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:
1069)
02-09 09:09:15.883: ERROR/AndroidRuntime(8313):     at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:
2751)

Thank you in advance

WarrenFaith
  • 57,492
  • 25
  • 134
  • 150
Mal
  • 27
  • 1
  • 6
  • Do [any](http://stackoverflow.com/questions/3563728/random-exception-android-database-sqlite-sqliteexception-unable-to-open-database) [of](http://stackoverflow.com/questions/3421360/android-sqlite-exception-how-to-fix) [these](http://stackoverflow.com/questions/4187631/unable-to-open-database-file-when-using-sqliteopenhelper-with-instrumentation-c) match your situation? – drudge Feb 08 '11 at 20:27
  • Can you hook up your device to your computer and do 'adb logcat' (or checkout out your device logs via the 'aLogCat' app)? There should be some more information in there. – ldx Feb 08 '11 at 21:11
  • Can you post the relevant sections of you AndroidManifest.xml file also, so we can make sure your permissions are correct? – Austyn Mahoney Feb 08 '11 at 21:44
  • Thanks for getting back to me guys. – Mal Feb 08 '11 at 22:21
  • Sorry, I can't see the option to add another question with a code block (this is my 1st post). I will paste in the LogCat readout below. – Mal Feb 08 '11 at 22:43
  • 02-08 22:30:36.030: WARN/dalvikvm(6067): threadid=1: thread exiting with uncaught exception (group=0x400259f8) 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): FATAL EXCEPTION: main 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.drager/com.drager.Drager}: android.database.sqlite.SQLiteException: unable to open database file 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2787) – Mal Feb 08 '11 at 22:44
  • 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): Caused by: android.database.sqlite.SQLiteException: unable to open database file 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): at android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:1902) 02-08 22:30:36.030: ERROR/AndroidRuntime(6067): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:884) – Mal Feb 08 '11 at 22:46
  • This is the stack trace for checkDataBase() as createDataBase() calls it to check the existence of your DB. In checkDataBase(), why don't you catch the SQL exception that is thrown because your DB file doesn't exist yet? That way you could return null, and the calling method would know that the DB should be created. – ldx Feb 09 '11 at 12:56

1 Answers1

0

Thanks IDX, your a very beautiful man, or woman! I tried what you suggested, with a bit of fiddling I got it, try/catches seem to be the key. Here is my amended code, hopefully it will help someone else.

public class DataBaseHelper extends SQLiteOpenHelper{
    //private static String DB_PATH = "/data/data/com.drager/databases/";
    private static String DB_PATH = Environment.getDataDirectory()+"/data/com.drager/databases/";
    final static String DB_NAME = "myDBName";
    private SQLiteDatabase myDataBase=null;
    private final Context myContext;
    private DataBaseHelper myDbHelper;
    private static String TAG ="MyActivity";

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

    }

    public DataBaseHelper createDataBase() throws IOException{
        boolean dbExist =checkDataBase();
        //SQLiteDatabase db_read =null;
        Log.i(TAG,"############value of dbExist"+dbExist+"##########");
        if (dbExist){
            //db must exist
        }
        else{
        myDbHelper = new DataBaseHelper(myContext);
        myDataBase = myDbHelper.getReadableDatabase();
        myDataBase.close();
        //this.getReadableDatabase();
            //db_read.close();

            try {
                copyDataBase();
            } catch (IOException e) {
                throw new Error("error copying database");
            }
        }
        return this;

    }

    public Cursor executeStatement(){
        Log.i(TAG,"in execute statement");
        Cursor cursor=null;

        cursor=myDataBase.rawQuery("SELECT _ID, title, value "+
                    "FROM constants ORDER BY title",
                     null);
        return cursor;
    }

    public String getTextViewItem(){

        Cursor cursor=null;

        String str="fffff";
        //store query results in cursor
        cursor=myDataBase.rawQuery("SELECT description FROM product_details" ,
                     null);
        Log.i(TAG,"################in gettextview, value of cursor ="+cursor);
        cursor.moveToNext();

        //cast cursor content from the index of 'description Column as a string
        str =cursor.getString(cursor.getColumnIndex("description"));

        return str;
    }

    public void copyDataBase() throws IOException{
        // open db as input stream
        InputStream myInput;
        //open empty db as output stream
        OutputStream myOutPut;
        try {
            myInput = myContext.getAssets().open(DB_NAME);

            //path to newly created db
            String outFileName =DB_PATH + DB_NAME;

            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);
            }
            myOutPut.flush();
            myOutPut.close();
            myInput.close();
            }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }




    }

    private boolean checkDataBase() {
        SQLiteDatabase checkDB = null;

        String myPath = DB_PATH + DB_NAME;

        try {
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
        } catch (SQLException e) {

            e.printStackTrace();
            return false;
        }

        if (checkDB != null){
            checkDB.close();
        }
        return true;
        //return checkDB !=null ? true : false;
    }

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

    @Override
    public synchronized void close(){
        if(myDataBase != null){
            myDataBase.close();
        }
        super.close();
    }

    @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

    }

}
Ram kiran Pachigolla
  • 20,897
  • 15
  • 57
  • 78
Mal
  • 27
  • 1
  • 6