1

I am trying to use my own created database in my android application using this tutorial http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/

I have my database in my assets folder have been working for 5 hours to get the work around but in vain.. i always keep getting

01-17 04:09:07.111: E/Database(1060): sqlite3_open_v2("/data/data/com.rahul.besttracker/databases/route", &handle, 1, NULL) failed

and

01-17 04:09:07.271: E/AndroidRuntime(1060): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rahul.besttracker/com.rahul.besttracker.Busdisplay}: android.database.sqlite.SQLiteException: unable to open database file

my code

public class Busdisplay extends ListActivity {
    TextView source, destination;
    String src, dest;
    ArrayList<String> mArrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        init();
        Bundle caught = getIntent().getExtras();
        src = caught.getString("source");
        dest = caught.getString("dest");

        DataBaseHelper entry = null;

        entry = new DataBaseHelper(Busdisplay.this);

        entry.openDataBase();

        mArrayList = entry.readEntry(src, dest);

        entry.close();

        setListAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, mArrayList));
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);
    }

    void init() {
        source = (TextView) findViewById(R.id.textView1);
        destination = (TextView) findViewById(R.id.textView2);
    }

}

My DBhelper class

public class DataBaseHelper extends SQLiteOpenHelper {

    // The Android's default system path of your application database.
    private static final String DB_PATH =   "/data/data/com.rahul.besttracker/databases/";

    private static final String DB_NAME = "route.db";
    private static final String DB_TABLE1 = "route1";
    private static final String DB_TABLE2 = "route2";
    private SQLiteDatabase myDataBase;

    private final Context myContext;

    /**
     * Constructor Takes and keeps a reference of the passed context in order to
     * access to the application assets and resources.
     * 
     * @param context
     */
    public DataBaseHelper(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    /**
     * Creates a empty database on the system and rewrites it with your own
     * database.
     * */
    public void createDataBase() throws IOException {

        boolean dbExist = checkDataBase();

        if (dbExist) {
            // do nothing - database already exist
        } else {

            // By calling this method and empty database will be created into
            // the default system path
            // of your application so we are gonna be able to overwrite that
            // database with our database.
            this.getReadableDatabase();

            try {

                copyDataBase();

            } catch (IOException e) {

                throw new Error("Error copying database");

            }
        }

    }

    /**
     * Check if the database already exist to avoid re-copying the file each
     * time you open the application.
     * 
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase() {

        SQLiteDatabase checkDB = null;

        try {
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null,
                    SQLiteDatabase.OPEN_READONLY);

        } catch (SQLiteException e) {

            System.out.print("ERROR");
        }

        if (checkDB != null) {

            checkDB.close();

        }

        return checkDB != null ? true : false;
    }

    /**
     * Copies your database from your local assets-folder to the just created
     * empty database in the system folder, from where it can be accessed and
     * handled. This is done by transfering bytestream.
     * */
    private void copyDataBase() throws IOException {

        // Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);

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

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

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    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) {
        try {
            createDataBase();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE1);
        db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE2);
        onCreate(db);
    }

    public ArrayList<String> readEntry(String src, String dest) {

        // TODO Auto-generated method stub
        Cursor c = myDataBase.rawQuery("SELECT route_no from " + DB_TABLE1
                + " WHERE stops LIKE '%" + src + "%,%" + dest + "%';", null);
        ArrayList<String> mArrayList = new ArrayList<String>();
        int index = c.getColumnIndex("route_no");
        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
            // The Cursor is now set to the right position
            mArrayList.add(c.getString(index));
        }
        return mArrayList;
    }

    // Add your public helper methods to access and get content from the
    // database.
    // You could return cursors by doing "return myDataBase.query(....)" so it'd
    // be easy
    // to you to create adapters for your views.

}
0x4b50
  • 629
  • 6
  • 18
Rahul Mehrotra
  • 639
  • 5
  • 15
  • 31
  • 1
    Consider using SQLiteAssetHelper (https://github.com/jgilfelt/android-sqlite-asset-helper), which implements the pattern you are trying to follow and saves you from having to write your own code for it. – CommonsWare Feb 19 '13 at 13:02
  • tried it still getting 01-17 04:09:07.111: E/Database(1060): sqlite3_open_v2("/data/data/com.rahul.besttracker/databases/route", &handle, 1, NULL) failed...same error – Rahul Mehrotra Feb 19 '13 at 13:39
  • this one worked..thanks bro... – Rahul Mehrotra Feb 20 '13 at 11:05

3 Answers3

3

I even had the same problem and get really frustrated about this, even I used this tutorial but it didn´t work. I searched many threads about this and find one...and even this doesn´t work...BUT I made a simple change. First, create two classes DatabaseHelper and CopyAdapter:

DatabaseHelper

    public class DatabaseHelper extends SQLiteOpenHelper{
private static String TAG = "TAG";
private static String DB_PATH = "/data/data/PLACE_HERE_YOUR_INTERNAL_PATH/databases/";
private static String DB_NAME = "PLACE_HERE_YOUR_DATABASE_NAME_WITH_EXTENSION";
private SQLiteDatabase mDataBase; 
private final Context mContext;

public DatabaseHelper(Context context) 
{
    super(context, DB_NAME, null, 1);
    DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
    this.mContext = context;
}   

public void createDataBase() throws IOException
{
    boolean mDataBaseExist = checkDataBase();
    Log.d(TAG,"create DB in Helper. Data exists?"+mDataBaseExist);
    if(!mDataBaseExist)
    {
        Log.d(TAG,"get Writable in DatabaseHelper");
        this.getWritableDatabase();
        try 
        {
            Log.d(TAG,"copy Database");
            copyDataBase();
        } 
        catch (IOException mIOException) 
        {Log.d(TAG,"copy not succeed");
            throw new Error("ErrorCopyingDataBase");

        }
    }
}

private boolean checkDataBase()
{
    SQLiteDatabase mCheckDataBase = null;
    try
    {
        String myPath = DB_PATH + DB_NAME;
        mCheckDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
    }
    catch(SQLiteException mSQLiteException)
    {
        Log.e(TAG, "DatabaseNotFound " + mSQLiteException.toString());
    }

    if(mCheckDataBase != null)
    {
        mCheckDataBase.close();
    }
    return mCheckDataBase != null;
}

private void copyDataBase() throws IOException
{
    Log.d(TAG,"copy");
    InputStream mInput = mContext.getResources().getAssets().open(DB_NAME);

    String outFileName = DB_PATH + DB_NAME;
    Log.d(TAG,"Output:"+outFileName);
    File createOutFile = new File(outFileName);
    if(!createOutFile.exists()){
        createOutFile.mkdir();
    }
    OutputStream mOutput = new FileOutputStream(outFileName);
    byte[] mBuffer = new byte[1024];
    int mLength;
    while ((mLength = mInput.read(mBuffer))>0)
    {
        mOutput.write(mBuffer, 0, mLength);
    }
    mOutput.flush();
    mOutput.close();
    mInput.close();
}

public boolean openDataBase() throws SQLException
{
    String mPath = DB_PATH + DB_NAME;
    mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
    return mDataBase != null;
}

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

@Override
public void onCreate(SQLiteDatabase db) 
{ }

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
{
    Log.vTAG, "UpgradingDatabase, This will drop current database and will recreate it");
}
   }

CopyAdapter

    public class CopyAdapter {

private final Context mContext;
private SQLiteDatabase mDb;
private DatabaseHelper mDbHelper;
    private static String TAG = "TAG";
private static String ACCOUNT_TABLE = "account";
public static String ACCOUNT_EXTRADATA = "extraData";
public static String ACCOUNT_ID = "ID";
public static String ACCOUNT_ADDITIONALDATA = "additionalData";
public static String ACCOUNT_DATA = "data";

public CopyAdapter(Context context) 
{
    this.mContext = context;
    mDbHelper = new DatabaseHelper(mContext);
    Log.d(TAG,"done");
}

public CopyAdapter createDatabase() throws SQLException 
{
    try 
    {
        Log.d(TAG,"create database");
        mDbHelper.createDataBase();
    } 
    catch (IOException mIOException) 
    {
        Log.e(TAG, mIOException.toString() + "  UnableToCreateDatabase");
        throw new Error("UnableToCreateDatabase");
    }
    return this;
}

public CopyAdapter open() throws SQLException 
{
    try 
    {
        Log.d(TAG,"Open");
        mDbHelper.openDataBase();
        mDbHelper.close();
        mDb = mDbHelper.getWritableDatabase();
    } 
    catch (SQLException mSQLException) 
    {
        Log.e(TAG, mSQLException.toString());
        throw mSQLException;
    }
    return this;
}

public void close() 
{
    mDbHelper.close();
}

public int countAccountData() 
{
    Cursor mCoursor = mDb.query(ACCOUNT_TABLE, new String[] {}, null, null, null, null, null);
    int mReturnedCount = mCoursor.getCount();
    mCoursor.close();
    return mReturnedCount;
}

public long insertData(String mExtra, String mAdditionalData, String mData) 
{
    ContentValues initialValues = new ContentValues();
    initialValues.put(ACCOUNT_EXTRADATA, mExtra);
    initialValues.put(ACCOUNT_ADDITIONALDATA, mAdditionalData);
    initialValues.put(ACCOUNT_DATA, mData);
    return mDb.insert(ACCOUNT_TABLE, null, initialValues);
}

public boolean updateData(int mPosition, String mExtra, String mAdditionalData, String mData) 
{
    ContentValues initialValues = new ContentValues();
    initialValues.put(ACCOUNT_EXTRADATA, mExtra);
    initialValues.put(ACCOUNT_ADDITIONALDATA, mAdditionalData);
    initialValues.put(ACCOUNT_DATA, mData);
    return mDb.update(ACCOUNT_TABLE, initialValues, "ID=" + mPosition, null) > 0;
}

public String retriveData(int mPosition)
{
    Cursor mCursor = mDb.query(ACCOUNT_TABLE, new String[] {ACCOUNT_DATA}, "ID=" + mPosition, null, null, null, null);
    mCursor.moveToFirst();
    String mReturn = mCursor.getString(mCursor.getColumnIndex(ACCOUNT_DATA));
    mCursor.close();
    return mReturn;
}

public String retriveAdditionalData(int mPosition)
{
    Cursor mCursor = mDb.query(ACCOUNT_TABLE, new String[] {ACCOUNT_ADDITIONALDATA}, "ID=" + mPosition, null, null, null, null);
    mCursor.moveToFirst();
    String mReturn = mCursor.getString(mCursor.getColumnIndex(ACCOUNT_ADDITIONALDATA));
    mCursor.close();
    return mReturn;
}

public boolean deleteAccount(int mPosition) 
{
    return mDb.delete(ACCOUNT_TABLE, ACCOUNT_ID + "=" + mPosition, null) > 0;
}
   }

And then just call where ever You need it:

   CopyAdapter  mDbHelper = new CopyAdapter(YourActivity.this);
    mDbHelper.createDatabase();

and be sure that You set

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

in your manifest.xml

I read so many variants for example, put your database file inside another folder in the asset folder, or rename your ending from Your database file to jpg, or put zip your database file before adding it to assets...FORGET ABOUT THAT. The only way I was able to make my app work, was to put the database file without folder or renaming or ziping inside my asset folder. Just only the pure file. Since this point, it worked without problems.

I don´t know from where I got this examples above, I can´t find the site anymore (but it is here on stackoverflow), but this, with a little workaround and putting the pure database file inside asset folder, was the solution. Hope it helps..

Opiatefuchs
  • 9,800
  • 2
  • 36
  • 49
2

The problem with your code is that when you use the getReadableDatabase() function it creates an empty database in the specified location. Take a look at this thread, it provided a solution for me when I had the same issue:

http://www.anddev.org/networking-database-problems-f29/missing-table-in-sqlite-with-specific-version-of-desire-hd-t50364.html

Etaoin
  • 8,444
  • 2
  • 28
  • 44
Martin
  • 166
  • 1
  • 15
0

Using SQLiteAssetHelper solved the problem.

Spacemonkey
  • 1,725
  • 3
  • 20
  • 44
Rahul Mehrotra
  • 639
  • 5
  • 15
  • 31