0

I am getting following exception while trying to load my Database file in android:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.jk.sqlite_test, PID: 32660
              java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.jk.sqlite_test/com.example.jk.sqlite_test.MainActivity}: com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/Data.db file (or .zip, .gz archive) in assets, or target folder not writable
                  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2493)
                  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2576)
                  at android.app.ActivityThread.access$1000(ActivityThread.java:155)
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
                  at android.os.Handler.dispatchMessage(Handler.java:102)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5539)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
               Caused by: com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/Data.db file (or .zip, .gz archive) in assets, or target folder not writable
                  at android.content.res.AssetManager.openAsset(Native Method)
                  at android.content.res.AssetManager.open(AssetManager.java:313)
                  at android.content.res.AssetManager.open(AssetManager.java:287)
                  at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.copyDatabaseFromAssets(SQLiteAssetHelper.java:436)
                  at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.createOrOpenDatabase(SQLiteAssetHelper.java:400)
                  at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:176)
                  at com.example.jk.sqlite_test.DatabaseAccess.open(DatabaseAccess.java:28)
                  at com.example.jk.sqlite_test.MainActivity.onCreate(MainActivity.java:25)
                  at android.app.Activity.performCreate(Activity.java:6289)
                  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2446)
                  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2576) 
                  at android.app.ActivityThread.access$1000(ActivityThread.java:155) 
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
                  at android.os.Handler.dispatchMessage(Handler.java:102) 
                  at android.os.Looper.loop(Looper.java:148) 
                  at android.app.ActivityThread.main(ActivityThread.java:5539) 
                  at java.lang.reflect.Method.invoke(Native Method) 
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
D/AppTracker: App Event: crash

Here are my codes :

package com.example.jk.sqlite_test;

import android.content.Context;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;

public class DatabaseOpenHelper extends SQLiteAssetHelper {

    private static final String DATABASE_NAME = "Data.db";
    private static final int DATABASE_VERSION = 3;

     public DatabaseOpenHelper(Context context) {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
}

And ,

package com.example.jk.sqlite_test;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;

public class DatabaseAccess {

    private SQLiteOpenHelper openHelper;
    private SQLiteDatabase database;
    private static DatabaseAccess instance;

    private DatabaseAccess(Context context) {
        this.openHelper = new DatabaseOpenHelper(context);
    }

    public static DatabaseAccess getInstance(Context context) {
        if (instance == null) {
            instance = new DatabaseAccess(context);
        }
        return instance;
    }   

    public void open() {
        this.database = openHelper.getWritableDatabase();
    }

    public void close() {
        if (database != null) {
            this.database.close();
        }
    }

    public String getAll()
    { 
         String str = "";

         Cursor cursor = database.rawQuery("SELECT * FROM pdata" , null);

         cursor.moveToFirst();

        while(!cursor.isAfterLast())
        {
             str += cursor.getString(1) + "\t" + cursor.getString(2) + "\t" + cursor.getString(3) + "\n";
        }
        return str;
    }
}

I guess I am using SQLite 3 Database so I kept the version as 3.

After creating the database file in SQLite Studio, I am not getting any file extension to the Database file so I kept the extension as db, as suggested in many answers to the questions of the same type.

I also tried using different version values and extensions like .sqlite/.sqlite3 but it didn't solve the issue.

Please Help ! Thank you.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Jamzy
  • 31
  • 6
  • Is the db `assets/databases/Data.db` rather than just `assets/Data.db`? It should be the first. (you may have to create the databases folder) – MikeT Apr 14 '18 at 09:09

3 Answers3

0

You are trying to open a database in write mode in a folder that is in read-only mode (assets).

Try to open the database in read-only mode with openHelper.getReadableDatabase().

xcesco
  • 4,690
  • 4
  • 34
  • 65
  • Okay you were right that exception is now gone but there arises a new one which says : " Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database" – Jamzy Apr 14 '18 at 09:23
  • Check database position. Is it in /assets/databases/Data.db or ins /assets/Data.db? Just another suggestion: avoid uppercase: put resource's name in lowercase with _. – xcesco Apr 14 '18 at 12:41
0

SQLiteOpenHelper requires that the file (extension is irrelevant other than the file name, along the the extension MUST be the same as the database name) to be in the assets/databases folder/directory not in the assets folder/directory. So you must have /assets/databases/Data.db.

If the databases folder doesn't exist in the assets then create it and then copy the Data.db file into the databases folder.

Additional

Having a closer look at your code you will enter and endless loop if you use the getAll method and there is at least 1 row as you movetoFirst but then don't moveToNext within the while loop.

I'd suggest that the getAll method should be :-

public String getAll()
{ 
    String str = "";
    Cursor cursor = database.rawQuery("SELECT * FROM pdata" , null)
    while(cursor.MoveToNext())
    {
         str += cursor.getString(1) + "\t" + cursor.getString(2) + "\t" + cursor.getString(3) + "\n";
    }
    return str;
}
Community
  • 1
  • 1
MikeT
  • 51,415
  • 16
  • 49
  • 68
  • I have already placed Data.db in the 'assets/databases/' but it does'nt work either as well. – Jamzy Apr 14 '18 at 09:26
  • try deleting the App's data and rerunning (you've probably inadvertently created it.) – MikeT Apr 14 '18 at 09:28
  • Uninstalled and tried again but no, not working. By the way, Is it okay if I have created a zip file and then laced it in assets folder ? – Jamzy Apr 14 '18 at 09:31
  • Sorry only just saw "I created the database file in Android Studio". As far as I'm aware you cannot create a valid database file in Android Studio. You need to create the file in an SQLite tool such as DB Browser for SQLite, SQLite Manager or DBeaver. Save the file, copy the saved file into the assets/databases folder (outside of Android Studio). The file name and database name MUST be the same. – MikeT Apr 14 '18 at 09:40
  • You might find [this answer helpful](https://stackoverflow.com/questions/49756892/reading-a-database-from-the-assets-folder/49768006#49768006). – MikeT Apr 14 '18 at 09:47
  • Thank you MikeT, Finally it worked and I found out that there was a fault in the file itself and was everything fine with my code and extension. – Jamzy Apr 14 '18 at 10:11
0
        public class DatabaseHelper extends SQLiteOpenHelper {

            private static String DB_NAME = "baseProject.db";
            private static String DB_PATH = "";
            private static final int DB_VERSION = 3;

     public DatabaseHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
            if (android.os.Build.VERSION.SDK_INT >= 17)
                DB_PATH = context.getApplicationInfo().dataDir + /databases/";
            else
                DB_PATH = "/data/data/" + context.getPackageName() + 
                    "/databases/";
            this.mContext = context;

            copyDataBase();

            this.getReadableDatabase();
        }


    private boolean checkDataBase() {
            File dbFile = new File(DB_PATH + DB_NAME);
            return dbFile.exists();
        }

        private void copyDataBase() {
            if (!checkDataBase()) {
                this.getReadableDatabase();
                this.close();
                try {
                    copyDBFile();
                } catch (IOException mIOException) {
                    throw new Error("ErrorCopyingDataBase");
                }
            }
        }

        private void copyDBFile() throws IOException {
            InputStream mInput = mContext.getAssets().open(DB_NAME);

            OutputStream mOutput = new FileOutputStream(DB_PATH + DB_NAME);
            byte[] mBuffer = new byte[1024];
            int mLength;
            while ((mLength = mInput.read(mBuffer)) > 0)
                mOutput.write(mBuffer, 0, mLength);
            mOutput.flush();
            mOutput.close();
            mInput.close();
        }

     @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) {
            if (newVersion > oldVersion)
                mNeedUpdate = true;
        }

}

try the above class

Hitesh Sarsava
  • 666
  • 4
  • 15