I've got an app using sqlite on android. Everything works fine, I can create, read and write the database without any problems.
BUT if I change the sourcecode in eclipse (doesn't matter what as long as it recompiles) the new apk is created and pushed to the emulator. Accessing the database now will result in
enter code here03-07 15:50:03.886: ERROR/AndroidRuntime(311): Caused by: android.database.sqlite.SQLiteException: file is encrypted or is not a database
Deleting the database file with the file explorer and accessing the database, will recreate the db and everything is fine again.
I'm sure the db is closed after every access.
I've found this error too! And Finally I've decided to create the DB file from my APP, executing some code like:
public class MyHelperSqliteHelper extends SQLiteOpenHelper{
// SQL to generate USER table
String sqlCreate = "CREATE TABLE 'user' " +
"('X_id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , " +
"'D_name' VARCHAR);";
...
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(sqlCreate);
}catch (SQLException e) {
e.printStackTrace();
}
}
...
}
Next step is export this file from DDMS view to file and open that file with SQLite manager. Here you will can to import all your datas and another tables.
Final step only need to export this database from SQLiteManager and if you open this file you can see it is encrypted.
I know this is a temporal solution but It can solve this problem, and you only need to do this one time and no more.
Good luck!
Related
I want to pre-create database for my android app. I use "SQLite Database Browser" and after create my database, i have copy the database to app folder "databases". In my app side i have add permission to write in sdcard (if need it)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and my code to open the database is:
String myPath = getApplicationContext().getFilesDir().getAbsolutePath().replace("files","databases")+ File.separator + "mydb.db";
db = SQLiteDatabase.openOrCreateDatabase(myPath, null);
Android can't to open my database and showing this error:
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
I have try the followings:
I have open the database file with Notepad++ and i confirmed the SQL format "SQLite format 3" in the header of the file.
I have add "android_metadata" table from "SQLite Database Browser" with this SQL statement:
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US');
INSERT INTO "android_metadata" VALUES ('en_US')
I have try to delete my database file from android and run my app to check if code can create database with this name and all it's ok, dabase created with no problems, after that i have run again my app to check if it can open the database and opening with no problems. I have create all tables i need it with android code and after succesfully database created, i have copy this file back to windows and opening with "SQLite Database Browser" to insert few data into table and after save changes, copy again back to android, but my app it can't to open it again!
I'm confused, where is the problem? Why if i try to edit or create database with "SQLite Database Browser" android it can't to open this?
Sorry for my english...
*Version of "SQLite Database Browser" is 3.9.1
Please make sure that you file path is empty or not. First you check that then after open it
String myPath = getApplicationContext().getFilesDir().getAbsolutePath().replace("files","databases")+ File.separator + "mydb.db";
File file = new File(myPath);
if (file.exists() && !file.isDirectory())
{
db = SQLiteDatabase.openOrCreateDatabase(myPath, null);
}
else
{
Log.i(TAG, "Database file not found");
}
My android app works with a provided DB populated and located on the asset folder. I recently had to start adding private datas in it so I used sqlcipher to encrypt it. So before starting:
The encryption goes well, since I can decrypt it easily and read it back. This is done with sqlcipher shell.
Everything was working like a charm with the db not crypted
What I was doing was, on the first launch of my app, creating a blank db on my phone, copy and past the content of the provided db in it and then, the user was able to have his own db on his phone without having to recreate it each time ( the db is pretty big ). Indeed, if the user already has the db on his phone for the further launch, he won't have to recreate it this way.
But with sqlcipher, it's not working anymore.
Important: When using sqlcipher with a non crypted db ( using "" as parameter for the related method like openDatabase ), it was working as well.
But when I try with the crypted db and with the password, what I have is the error
file is encrypted or is not a database: create locale table failed
This happens after I created a blank db using this:
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase("password").close();
I then try to open it with the following instruction:
//Open the database
String myPath = DB_PATH + DATABASE_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, "password", null, SQLiteDatabase.OPEN_READWRITE);
And then happens the error. Someone has an idea please? I'm saddly not an android expert, using a db was already difficult but as you can guess it's getting on another level now. Any help would be welcome. Thanks in advance !
Finally solve my problem after a long search following this link: Sqlcipher __ CREATE TABLE android_metadata failed
The error was coming from the way I was opening my db, which changes whether you use sqlcipher or sqlite.
Old way to open the db using sqlite:
myDataBase = SQLiteDatabase.openDatabase(myPath, "password", null, SQLiteDatabase.OPEN_READWRITE);
New way using sqlcipher, with a SQLiteDatabaseHook:
SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
public void preKey(SQLiteDatabase database) {
}
public void postKey(SQLiteDatabase database) {
database.rawExecSQL("PRAGMA cipher_migrate;");
}
};
myDataBase = SQLiteDatabase.openOrCreateDatabase(myPath, "password", null, hook);
As I changed the android version and the path from externalized to the default database-folder, I don't know where the error come from.
I found that the reason might be problems accessing the journal file is locked (it is created by the program).
the "test" is reading data and if it exists it updates and if not it inserts. This is done in a loop while reading lines from a file. For testing purpose i simplified it but the error is the same.
package ...;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class test {
public test(SQLiteDatabase MyDB)
{
MyDB.execSQL("CREATE TABLE IF NOT EXISTS testtable (mytext TEXT, number INT PRIMARY KEY)", new String[] {});
for (int i = 1; i < 5; i++)
{
String[] ColArray = { "any text", String.valueOf(i) };
Cursor readCursor = MyDB.rawQuery("SELECT mytext FROM testtable WHERE number=?", new String[] { String.valueOf(i) });
if (!readCursor.moveToNext()) // Error when executing moveToNext
/*
In the 2nd time it runs over this point an Error occurs:
android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14)
I need to remove the journal file to be able to connect to the database it again - the change made by the Insert/Update is successfully saved!
*/ {
readCursor.close();
MyDB.execSQL("INSERT INTO testtable (mytext, number) VALUES(?, ?)", ColArray);
}
else {
readCursor.close();
MyDB.execSQL("UPDATE testtable SET mytext=? WHERE number=?", ColArray);
}
}
}
}
MyDB is a valid DB-Connection.
1) The Table is created
2) The Table is READ but Line 1 is not found
2a) READ again is possible until now if the read is closed.
3) Line 1 is INSERTED
4) when trying to READ again (the line 2 would not be found, too), moving the cursor fails.
The journalfile need to be deleted manually or the app will fail to start again when trying to connect.
Please Help! Thank you.
Maybe you should use the specialized insert and update methods.
In the documentation of the SQLiteDatabase it says for execSQL:
Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
There are specialized methods for insert and update with similar names. I guess, that there is some problem generated, when the unspecific "execSQL" statement is used.
i solved it after hours of testing.
possibly the sqlite version is different in the old and new system... i changed the rom again - for some reason, this time i didn't copy the databasefile into the data-folder. Instead i let the program create a empty database and imported the data from text by the program itself from a csv-export.
I currently don't know if the problem was within the rom or (what seem to be the reason in my opinion) i created the problem by using the origin database which might be read and writeable but has problems when the journalfile should get processed. if somebody has an equal problem, he should try to create a new empty database in the new system.
I have an encyprted SQLite database file that is being exported from an existing application using System.Data.SQLite. Based on what I can find, System.Data.SQLite uses 128-bit RC4 encryption.
When I try to load this database in my Android application with SQLCipher, I get the following error "file is encrypted or is not a database". I have tried using a database hook which sets the pragma key = rc4, but this does not seem to help. The only program I have been able to find that can open this database file is SQLite2009 Pro Enterprise Manager. It opens it with no issue, allows me to browse, and run queries.
Here is the code I am currently using:
try
{
SQLiteDatabase.loadLibs(activity);
//this function copies the db file from the project assets to the data/databases folder
copydatabase();
File databaseFile = activity.getApplicationContext().getDatabasePath("someDB.db3");
SQLiteDatabaseHook hook = new SQLiteDatabaseHook(){
public void preKey(SQLiteDatabase database){
database.execSQL("pragma cipher = rc4");
}
public void postKey(SQLiteDatabase database){
database.execSQL("pragma cipher = rc4");
}
};
SQLiteDatabase database = SQLiteDatabase.openDatabase(databaseFile.getAbsolutePath(), "mypassword", null, SQLiteDatabase.NO_LOCALIZED_COLLATORS|SQLiteDatabase.OPEN_READWRITE, hook);
Cursor cursor = database.rawQuery("SELECT * FROM SOMETABLE;", null);
if (cursor.moveToFirst()){
do{
String data = cursor.getString(cursor.getColumnIndex("SOME_COLUMN"));
}while(cursor.moveToNext());
}
cursor.close();
}
catch(Exception ex)
{
Log.e(ex.getMessage().toString(), ex.getStackTrace().toString());
}
Any ideas on what I am doing wrong?
Looks like I got an answer over on the SQLCipher Google Group:
If your SQLite database was encrypted outside of SQLCipher, you will
first need to export that database to a plain-text SQLite database.
Once you have done that you can use the sqlcipher_export convenience
function to create an SQLCipher encrypted version your plain-text
database. Please refer to example 1 1 in the documentation for
sqlcipher_export for your scenario.
http://sqlcipher.net/sqlcipher-api#sqlcipher_export
Your database may be of an older SQLCipher version than the one you are trying to open it with.
Try to execute the query PRAGMA cipher_migrate; just after opening and setting the key of the database.
I am experiencing some trouble with an SQLIte database in my Android application.
The issue is that the database is never updated, not even on multiple restarts of the emulator, of Eclipse or after deletion from DDMS.
This is my onCreate method, located in a class that extends SQLiteOpenHelper:
public void onCreate(SQLiteDatabase database) {
try {
database.execSQL(ESSENCE_TABLE_CREATE);
database.execSQL(PACCO_TABLE_CREATE);
database.execSQL(TAVOLE_TABLE_CREATE);
database.rawQuery("insert into essenza values(1, 'Rovere')",
null); // added later
} catch (SQLException e) {
Log.e("DB", e.getMessage());
}
}
After instantiating the helper, I request a reference to the database:
helper = new DBHelper(context, dbpath + "/" + DATABASE_NAME);
database = helper.getWritableDatabase();
It seems that the rawQuery statement (which was added at a later time) is not executed and that the database in use is instead cached from a previous version. I also tried to change the version of the database, but it did not work. Am I missing something? Thanks in advance.
You have two options:
Use DDMs to delete the database file from your device (look in /data/data/). This will force Android to run onCreate again.
In your constructor, increment the database version you pass to SQLiteOpenHelper. Add your raw query to onUpgrade.
You probably want option 1. Option 2 is better if you have users of your app whose databases you want to update.