Database not getting copied properly in OnePlus Two
Asked Answered
C

3

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

Cohune answered 21/9, 2015 at 14:1 Comment(15)
void exportDB. Make that boolean and add code in case currentDB does not exist. That code will/can not work.Landgrave
Some times i found the same issue.Cuba
I am experimenting problems with and app I'm developing in my OP2 and it's driving me crazyJohnston
did you found any solution to this problem ?Dogger
No :/ still trying to figure out what's wrongJohnston
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'.Lebrun
I am also still suffering from this problemCohune
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.Lebrun
I am also facing same issue with oxygenOS on OnePlus 2 devices. Did you find any solution for this?Elda
i have created oneplus thread kindly comment here: forums.oneplus.net/threads/…Huron
Do you have specific android tables like sqlite_sequence and android_metadata? I faced with similar issue #9323399 and the error was gone when I re-create the database with all the special tablesLamented
any updates on this? I'm facing sqlite problems with sqlite-asset-helper on oneplus devices as well...Higginson
@JigneshAnsodariya: Both copyDataBase and exportDB methods executing properly without any Exception ?Denby
@Higginson please see my answer o thisCohune
@ρяσѕρєя K yes executing properlyCohune
C
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!

Cohune answered 14/12, 2015 at 6:17 Comment(0)
A
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);
Aeropause answered 11/12, 2015 at 14:58 Comment(5)
I guess if that's correct than this line in sqlite-asset-helper is wrong as well: github.com/jgilfelt/android-sqlite-asset-helper/blob/master/… - right?Higginson
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.Aeropause
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?Higginson
IMO, It would be better to use Context.getDatabasePath(). But it doesn't mean context.getApplicationInfo().dataDir + "/databases" is wrong.Aeropause
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.Nutty
C
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!

Cohune answered 14/12, 2015 at 6:17 Comment(0)
P
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.

Perales answered 10/2, 2016 at 12:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.