Question

I have tried to copy my db in the asset folder to the internal app memory.

The db contains two table. One table is totally empty that should allow the user to insert their data into the table. Another table is preloaded with data that provides the information of the app (the reason why i need to load the preloaded db into the app) Should i have two separate db because when i was dealing with the preloaded db, the db was populating into the app memory just fine but for some reason now i could not do so because of that extra table.

Is it possible that the DB i put in my asset is corrupted because i do not have android-metadata inside? The db in my asset folder is just created with my data from CSV sheet.

Before this problem, i refractor my package name and changed them in manifest as well. Could it be one of the problem?

Heres the code

DBHelper.class

@Override
public void onCreate(SQLiteDatabase db)
{
    db.execSQL(DB_CREATE_SQL);
    db.execSQL(DB_CREATE_SQL_FOR_GAME);
}
    public void createDatabase(Context context) throws IOException
{
    Log.d("Create Database","In method");
    // If database does not exist, copy it from the asset
    if (checkDatabase() == false)
    {
        try
        {
            // Copy the database from assets
            copyDatabase(context);
            Log.d("Create Database","Copying");
        }
        catch (IOException mIOException)
        {
            Log.d("Create Database","Failed");
            throw new Error("ErrorCopyingDataBase");
        }
    }
}


public void copyDatabase(Context context) throws IOException
{
    // Open your local db as the input stream
    InputStream myInput = context.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[10240];
    int length;
    while ((length = myInput.read(buffer)) > 0)
    {
        myOutput.write(buffer, 0, length);
    }
    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
}

public boolean checkDatabase()
{

    String myPath = DB_PATH + DB_NAME;
    File f = new File(myPath);
    return f.exists();
}

I am actually getting IO exception whenever i run the app because i am actually populating the asset right after the app is launched.

Logcat

09-25 16:55:42.878: E/SQLiteDatabase(28815): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:278)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:217)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:464)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:186)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)

I have tried to just copy the database into the folder after using getWritableDatabase() to create the path of the db (which would mean it will override any existing one) and i got this error

09-26 11:09:46.370: E/System(2444): Uncaught exception thrown by finalizer
09-26 11:09:46.380: E/System(2444): java.io.IOException: close failed: EIO (I/O error)
09-26 11:09:46.380: E/System(2444):     at libcore.io.IoUtils.close(IoUtils.java:41)
09-26 11:09:46.380: E/System(2444):     at java.io.RandomAccessFile.close(RandomAccessFile.java:166)
09-26 11:09:46.380: E/System(2444):     at java.io.RandomAccessFile.finalize(RandomAccessFile.java:175)
09-26 11:09:46.380: E/System(2444):     at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:186)
09-26 11:09:46.380: E/System(2444):     at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:169)
09-26 11:09:46.380: E/System(2444):     at java.lang.Thread.run(Thread.java:856)
09-26 11:09:46.380: E/System(2444): Caused by: libcore.io.ErrnoException: close failed: EIO (I/O error)
09-26 11:09:46.380: E/System(2444):     at libcore.io.Posix.close(Native Method)
09-26 11:09:46.380: E/System(2444):     at libcore.io.BlockGuardOs.close(BlockGuardOs.java:75)
09-26 11:09:46.380: E/System(2444):     at libcore.io.IoUtils.close(IoUtils.java:38)
09-26 11:09:46.380: E/System(2444):     ... 5 more
Was it helpful?

Solution

It actually the way i did my code. In my code, i used getWritableDatabase() to create the directory of /data/data//databases. However a dummy db will also be created when i run getWritableDatabase().

So basically instead of running getWritableDatabase(), i made the directory with

public void createDirectory()
    {
        File dbDirectory = new File(DB_PATH);
         if (!dbDirectory.exists())
                dbDirectory.mkdirs();
    }

then i check whether is there a db inside of my /data/data//databases directory and there should not be any database. Hence i am able to copy the db from asset as there is no database in the folder.

Hope this helps anyone with similar problem.

OTHER TIPS

Try this Before you accessing the database.

            InputStream input = getResources().getAssets().open("db");
            File f = new File("DB_PATH/databases");
            if (f.mkdirs())
            {
                File ff=new File("DB_PATH/databases");
                FileOutputStream output = new FileOutputStream(ff);
                int data = 0;
                byte[] buffer = new byte[1024];
                while ((data = input.read(buffer)) > 0) {
                    output.write(buffer, 0, data);
                }

                input.close();
                output.close();
                Log.d("File", "File Copied!");
            } else {
                Log.d("File", "AlreadyExists!");
            }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

Try this Hope this help you

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

import java.io.BufferedInputStream;
import java.io.IOException;

public class SmartOpenHelper extends SQLiteOpenHelper {

    private Context context;
    private String DB_SQL;

    SmartOpenHelper(Context context, String dbname, int dbversion, String dbSqlName) throws IOException {
        super(context, dbname, null, dbversion);
        this.context = context;
        this.DB_SQL = dbSqlName;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            BufferedInputStream inStream = new BufferedInputStream(context.getAssets().open(DB_SQL));
            String sql = "";
            int character = -2;
            do {
                character = inStream.read();
                if ((character != -1) && (character != -2))
                    sql += (char) character;
                else
                    break;
            } while (true);
            System.out.println("onCreate DB SQL = " + sql.split("\n"));
            String[] arrSQL = sql.split("\n");

            for (int i = 0; i < arrSQL.length; i++) {
                db.execSQL(arrSQL[i]);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        try {
            BufferedInputStream inStream = new BufferedInputStream(context.getAssets().open(DB_SQL));
            String sql = "";
            int character = -2;
            do {
                character = inStream.read();
                if ((character != -1) && (character != -2))
                    sql += (char) character;
                else
                    break;
            } while (true);

            System.out.println("onUpgrade DB SQL = " + sql.split("\n"));
            String[] arrSQL = sql.split("\n");
            for (int i = 0; i < arrSQL.length; i++) {
                db.execSQL(arrSQL[i]);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public synchronized void close() {
        super.close();
    }

}

How to use

SmartOpenHelper openHelper = new SmartOpenHelper(this.context, DATABASE_NAME, DATABASE_VERSION, DATABASE_SQL);
SQLiteDatabase db = openHelper.getWritableDatabase();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top