22

I am creating an Android Application and I am using sqlite database in it. for that I have placed a sqlite file in assets folder of project and I am copying this file to phone while my first execution of application using code below.

 private void copyDataBase() throws IOException {
    new File(DB_PATH).mkdirs();
    InputStream myInput = appContext.getAssets().open(DB_NAME);
    String outFileName = DB_PATH + DB_NAME;
    OutputStream myOutput = new FileOutputStream(outFileName);
    byte[] buffer = new byte[1024];
    int length;

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

    myOutput.flush();
    myOutput.close();
    myInput.close();
}

but I am getting this errors.

 09-21 18:03:56.841: E/SQLiteLog(7850): (1) no such table: tbl_player

but this table is exists in assets file. so I fetched database file from phone using this method.

public static void exportDB(String databaseName, Context context) {
    try {
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();

        if (sd.canWrite()) {
            String currentDBPath = "//data//" + context.getPackageName()
                    + "//databases//" + databaseName + "";
            String backupDBPath = "sensor_game.db";
            File currentDB = new File(data, currentDBPath);
            File backupDB = new File(sd, backupDBPath);

            if (currentDB.exists()) {
                FileChannel src = new FileInputStream(currentDB)
                        .getChannel();
                FileChannel dst = new FileOutputStream(backupDB)
                        .getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
            }
        }

    } catch (Exception e) {

    }
}

and I found that there is no table in fetched database file.

Note: This issue is occurs only in OnePlus Two and working fine in Nexus 4, Htc 820,Moto E,Galxy S3and Galaxy Quottro

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Jignesh Ansodariya
  • 12,583
  • 24
  • 81
  • 113
  • `void exportDB`. Make that boolean and add code in case currentDB does not exist. That code will/can not work. – greenapps Sep 21 '15 at 14:28
  • Some times i found the same issue. – M D Sep 21 '15 at 14:38
  • I am experimenting problems with and app I'm developing in my OP2 and it's driving me crazy – Frildoren Oct 07 '15 at 17:33
  • did you found any solution to this problem ? – varun bhardwaj Oct 08 '15 at 12:10
  • No :/ still trying to figure out what's wrong – Frildoren Oct 08 '15 at 13:53
  • Run into a user of my app with the similar Problem. `statement aborts at 15: [SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1] 10-13 14:20:35.633 E/SQLiteDatabase(15040): Failed to open database '/data/data/myapp/databases/app.db'. 10-13 14:20:35.633 E/SQLiteDatabase(15040): android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/myapp/databases/app.db' to 'de_DE'.` – David Oct 13 '15 at 13:15
  • I am also still suffering from this problem – Jignesh Ansodariya Oct 14 '15 at 04:23
  • now i have total of 4 users where changing the locale in sqlite fails. All users are running the oneplustwo. It works for all other 99,9% of the devices. The latest Oxygen update made no difference. – David Oct 18 '15 at 07:15
  • I am also facing same issue with oxygenOS on OnePlus 2 devices. Did you find any solution for this? – Mitesh Sharma Oct 24 '15 at 18:29
  • i have created oneplus thread kindly comment here: https://forums.oneplus.net/threads/cannot-copy-database-from-assets-folder-of-app-to-phone-in-op2.385561/#post-13768775 – Calvin Oct 26 '15 at 05:43
  • Do you have specific android tables like sqlite_sequence and android_metadata? I faced with similar issue http://stackoverflow.com/questions/9322899/cannot-open-my-database-on-the-android-device-but-can-on-the-emulator and the error was gone when I re-create the database with all the special tables – forcelain Oct 26 '15 at 15:27
  • any updates on this? I'm facing sqlite problems with sqlite-asset-helper on oneplus devices as well... – swalkner Dec 01 '15 at 15:15
  • @JigneshAnsodariya: Both `copyDataBase ` and `exportDB ` methods executing properly without any Exception ? – ρяσѕρєя K Dec 07 '15 at 07:45
  • @swalkner please see my answer o this – Jignesh Ansodariya Dec 14 '15 at 12:51
  • @ρяσѕρєя K yes executing properly – Jignesh Ansodariya Dec 14 '15 at 12:53

3 Answers3

6

Database path may be different in different devices. You need to use Context.getDatabasePath(String) in order to get database path.

e.g.

File backupDB = context.getDatabasePath(backupDBPath);
frogatto
  • 28,539
  • 11
  • 83
  • 129
Ugur Ozmen
  • 580
  • 3
  • 10
  • 1
    I guess if that's correct than this line in ```sqlite-asset-helper``` is wrong as well: https://github.com/jgilfelt/android-sqlite-asset-helper/blob/master/library/src/main/java/com/readystatesoftware/sqliteasset/SQLiteAssetHelper.java#L109 - right? – swalkner Dec 11 '15 at 15:13
  • IMO it is still better than fully hard coded version. At least it will behave correctly when app is moved to sdcard. Anyway, I think there is no need for trying to assume path, while system is already providing it. – Ugur Ozmen Dec 11 '15 at 15:39
  • I don't get your comment, sorry; I mean: if you're right that ```getDatabasePath()``` has to be used, that should be the default in ```sqlite-asset-helper``` as well, right? – swalkner Dec 11 '15 at 15:54
  • 1
    IMO, It would be better to use Context.getDatabasePath(). But it doesn't mean `context.getApplicationInfo().dataDir + "/databases"` is wrong. – Ugur Ozmen Dec 11 '15 at 16:14
  • IMO, It's up to Android to decide where should databases to put not the device unless vendors change Android codes and build their own one. – frogatto Dec 13 '15 at 11:55
3

After a long tries and searches I forced to assume that there should be a bug in OP2 manufacturing as it is working fine in all other devices.

and I changed my approach to create database using query rather than copying database file from assets. like code below

import java.io.File;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MySQLiteHelper extends SQLiteOpenHelper implements DBConstants {

private static MySQLiteHelper mInstance = null;
private SQLiteDatabase myDataBase;
private static String DB_PATH = "";

public MySQLiteHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    try {
        if (checkDataBase())
            openDataBase();
        else
            myDataBase = this.getReadableDatabase();
    } catch (Exception e) {
    }
}

public static MySQLiteHelper instance(Context context) {

    File outFile = context.getDatabasePath(DATABASE_NAME);
    DB_PATH = outFile.getPath();

    if (mInstance == null) {
        mInstance = new MySQLiteHelper(context);
    }

    return mInstance;
}

private void openDataBase() throws Exception {
    try {
        myDataBase = SQLiteDatabase.openDatabase(DB_PATH, null,
                SQLiteDatabase.OPEN_READWRITE);
    } catch (SQLException e) {
        // TODO: handle exception
    }
}

private boolean checkDataBase() {
    SQLiteDatabase checkDB = null;
    try {
        checkDB = SQLiteDatabase.openDatabase(DB_PATH, null,
                SQLiteDatabase.OPEN_READONLY);

    } catch (SQLiteException e) {
        /** database does't exist yet. */
    } catch (Exception e) {
    }
    if (checkDB != null) {
        checkDB.close();
    }
    return checkDB != null ? true : false;
}

@Override
public void onCreate(SQLiteDatabase db) {

    Log.v("log_tag", "onCreate");
    myDataBase = db;

    // creating a sample table
    String CREATE_DEVICE_TABLE = "CREATE TABLE " + DEVICE + " ("
            + KEY_DEVICEID + " TEXT, " + KEY_OPERATOR + " TEXT, "
            + KEY_DEVICENAME + " TEXT, " + KEY_DEVICETOTALMEMORY
            + " INTEGER, " + KEY_SCREENWIDTH + " INTEGER, "
            + KEY_SCREENHEIGHT + " INTEGER, " + KEY_OPERATINGSYSTEM
            + " TEXT)";

    db.execSQL(CREATE_DEVICE_TABLE);

    // other tables also can be created from here.
}

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

    // Create tables again (as per requirement)
    this.onCreate(db);
}

public Cursor rawQuery(String qry) {
    return myDataBase.rawQuery(qry, null);
}

public long insert(String tableName, ContentValues cv) {
    return myDataBase.insert(tableName, null, cv);
}

public void insertWithOnConflict(String tableName, ContentValues cv,
        int flag) {
    myDataBase.insertWithOnConflict(tableName, null, cv, flag);

}

public long update(String tableName, ContentValues cv, String whereClose) {
    return myDataBase.update(tableName, cv, whereClose, null);

}

public int deleteData(String table_name, String whereClause) {
    return (int) myDataBase.delete(table_name, whereClause, null);
}

}

and it worked for me

Thanks!

Jignesh Ansodariya
  • 12,583
  • 24
  • 81
  • 113
3

I have found solution for this, I have used below function :

public void createDb() {
        boolean dbExist = checkDataBase();

        if (dbExist) {
            // do nothing - database already exist
        } else {
            // call close() for properly copy database file
            this.getReadableDatabase().close();
            try {
                copyDataBase();
            } catch (IOException e) {
                e.printStackTrace();
                throw new Error("Error copying database");
            }
        }
    }

As per this post we need to call close() and you can push database to Oneplus two devices also.

Community
  • 1
  • 1
Jaiprakash Soni
  • 4,100
  • 5
  • 36
  • 67