Search code examples
androidsqlitejava-io

Copy database from assets folder


I am creating a Dictionary application which uses an existing sqlite database. I have placed my database in assets folder and I am using the following code to copy the database when the app is started for first time. (I have borrowed the idea from this post)

DatabaseHelper.java

public class DatabaseHelper {

private static String DB_PATH = "";
private static String DB_NAME = "abc.sqlite";
private SQLiteDatabase myDatabase;
private Context myContext;

public DatabaseHelper(Context context) {

    myContext = context;

    if (android.os.Build.VERSION.SDK_INT >= 17)
        DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
    else
        DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
    Log.d("path", DB_PATH);
}

public void copyDatabase() {

        InputStream myInput;
        OutputStream outStream;
        try {
            myInput = myContext.getAssets().open(DB_NAME);
            String file = DB_PATH + DB_NAME;
            outStream = new FileOutputStream(file);

            byte[] buffer = new byte[1024];
            int length = 0;
            while ((length = myInput.read(buffer)) >= 0) {
                outStream.write(buffer, 0, length);             
            }
            outStream.flush();
            myInput.close();
            outStream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

And then I call the above copyDatabase() method form my MainActivity. Here is the code.

public class MainActivity extends Activity {
    DatabaseHelper myDbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.layout);
        myDbHelper = new DatabaseHelper(getApplicationContext());
        myDbHelper.copyDatabase();


    }

}

But the problem is that Android does not copy the database. I have used Log tool, and I found out that the while loop never runs. What's the problem in this code. Thanks.


Solution

  • Change your while loop as below:

    Besides your condition >= greater than or equal to change it to only > Greater than

    while ((length = myInput.read(buffer)) > 0) {
                outStream.write(buffer, 0, length);             
            }
    

    Try out the below code which will work for you like charm.

    public class DataBaseHelper extends SQLiteOpenHelper {
        private Context mycontext;
        private String DB_PATH; 
    
        private static String DB_NAME = "abc.sqlite";
        public SQLiteDatabase myDataBase;
    
    
        public DataBaseHelper(Context context) throws IOException {
            super(context,DB_NAME,null,1);
            this.mycontext=context;
            boolean dbexist = checkdatabase();
            if (dbexist) {
                  opendatabase(); 
            } else {
                System.out.println("Database doesn't exist");
                createdatabase();
            }
        }
    
        public void createdatabase() throws IOException {
            boolean dbexist = checkdatabase();
            if(!dbexist) {
                this.getReadableDatabase();
                try {
                    copydatabase();
                } catch(IOException e) {
                    throw new Error("Error copying database");
                }
            }
        }   
    
        private boolean checkdatabase() {
    
            boolean checkdb = false;
            try {
                String myPath = DB_PATH + DB_NAME;
                File dbfile = new File(myPath);
                checkdb = dbfile.exists();
            } catch(SQLiteException e) {
                System.out.println("Database doesn't exist");
            }
            return checkdb;
        }
    
        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 byte to inputfile to 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_READWRITE);
        }
    
        public synchronized void close() {
            if(myDataBase != null) {
                myDataBase.close();
            }
            super.close();
        }
    
    }
    

    In your MainActivity you just now need to create and instance of your DatabaseHelper class others will managed on it own.

    public class MainActivity extends Activity {
        DatabaseHelper myDbHelper;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.layout);
            myDbHelper = new DatabaseHelper(MainActivity.this);
          }
    
    }