0

In my activity I create an object to copy a database from asset folder to app database, everything works fine in emulator but in the device, I get no such file or directory Error on

OutputStream os = new FileOutputStream(dbFile);

I have permission needed:

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

I call in MainActivity:

db = new ExternalDB(this); 

and in ExternalDB (Is SqliteOpenHelper):

ExternalDB(Context context){
    super(context, DB_Name, null, DATABASE_VERSION);
    mycontext = context;
    AssetDatabaseOpenHelper adb = new AssetDatabaseOpenHelper(context,DB_Name);
    db = adb.OpenDatabase();
}

And AssetDatabaseOpenHelper:

public class AssetDatabaseOpenHelper {

private static String DB_NAME;

private Context context;

AssetDatabaseOpenHelper(Context context, String DB_NAME){
    this.context = context;
    AssetDatabaseOpenHelper.DB_NAME = DB_NAME;
}

public SQLiteDatabase OpenDatabase(){
    File dbFile = context.getDatabasePath(DB_NAME);

    if(!dbFile.exists()){
        try{
            CopyDatabase(dbFile);
        }
        catch (IOException e){
            throw  new RuntimeException("Error Creating source database", e);
        }
    }

  //  copyDataBase();
    return SQLiteDatabase.openDatabase(dbFile.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
}
private void CopyDatabase(File dbFile) throws IOException{
    InputStream is = context.getAssets().open(DB_NAME);
    OutputStream os = new FileOutputStream(dbFile);

    byte[] buffer = new byte[1024];

    while(is.read(buffer)>0){
        os.write(buffer);
    }
    os.flush();
    os.close();
    is.close();
}
}

As I Mentioned i get this error on this line:

OutputStream os = new FileOutputStream(dbFile);
Ronak Thakkar
  • 2,515
  • 6
  • 31
  • 45
Alireza Pir
  • 878
  • 1
  • 16
  • 41
  • There's a solution to a similar question [here](https://stackoverflow.com/questions/18805874/copy-database-from-assets-to-databases-folder/18806587) – TennyApps Jul 11 '18 at 11:38
  • @Ten I get exact same error when i use method mentioned in question you referenced... – Alireza Pir Jul 11 '18 at 18:16

3 Answers3

1

CopyDatabase get's called when dbFile does not exist. Right? And then you tell the FileOutputStream to open the dbFile which we have established does not exist. Thus, no such file or directory Error. Seems legit, doesn't it?

1

The error is arising because the folder "databases" does not exist so the database cannot be copied

Try:

  public SQLiteDatabase OpenDatabase() {
        File dbFile = context.getDatabasePath(DB_NAME);
        if (!dbFile.exists()) {
            try {

                //check if "databases" folder exists and create it if needed
                File destDir = context.getDatabasePath(DB_NAME).getParentFile();
                if(!destDir.exists()){
                    destDir.mkdirs();
                }

                CopyDatabase(dbFile);
            } catch (IOException e) {
                throw new RuntimeException("Error Creating source database", e);
            }
        } // copyDataBase();
        return SQLiteDatabase.openDatabase(dbFile.getPath(), null, SQLiteDatabase.OPEN_READWRITE);
    }
TennyApps
  • 189
  • 8
0

For Any One having same problem, Hard Coding database paths didn't work for me and finaly writing copy function like this solved my problem:

    /**
 * Copy database file from assets folder inside the apk to the system database path.
 * @param context Context
 * @param databaseName Database file name inside assets folder
 * @param overwrite True to rewrite on the database if exists
 * @return True if the database have copied successfully or if the database already exists without overwrite, false otherwise.
 */
private boolean copyDatabaseFromAssets(Context context, String databaseName , boolean overwrite)  {

    File outputFile = context.getDatabasePath(databaseName);
    if (outputFile.exists() && !overwrite) {
        return true;
    }

    outputFile = context.getDatabasePath(databaseName + ".temp");
    outputFile.getParentFile().mkdirs();

    try {
        InputStream inputStream = context.getAssets().open(databaseName);
        OutputStream outputStream = new FileOutputStream(outputFile);


        // transfer bytes from the input stream into the output stream
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, length);
        }

        // Close the streams
        outputStream.flush();
        outputStream.close();
        inputStream.close();

        outputFile.renameTo(context.getDatabasePath(databaseName));

    } catch (IOException e) {
        if (outputFile.exists()) {
            outputFile.delete();
        }
        return false;
    }

    return true;
}

I had to create the folder databases first and then try to create database file.

from this answer: https://stackoverflow.com/a/29058717/4225644

Alireza Pir
  • 878
  • 1
  • 16
  • 41