Android Sqlite singleton db filestream update failed
android, sqlite
Solution
I faced the same problem `database disk image is malformed` while I was trying to access database when it was updating itself. So, I followed the below way.
`DataBaseHelper`
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
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 DataBaseHelper extends SQLiteOpenHelper {
private static final String TAG = DataBaseHelper.class.getSimpleName();
private static String DB_PATH = "/data/data/YOUR_PACKAGE/databases/";
private static String DB_NAME = "XXX";
private SQLiteDatabase mDataBase;
private final Context mContext;
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
this.mContext = context;
}
public void createDataBase() throws IOException {
boolean mDataBaseExist = checkDataBase();
if (!mDataBaseExist) {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException mIOException) {
throw new Error("ErrorCopyingDataBase");
}
}
}
private boolean checkDataBase() {
SQLiteDatabase mCheckDataBase = null;
try {
String mPath = DB_PATH + DB_NAME;
File pathFile = new File(mPath);
if(pathFile.exists()) {
mCheckDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
}
} catch (SQLiteException mSQLiteException) {
Log.e(TAG, "DatabaseNotFound " + mSQLiteException.toString());
}
if (mCheckDataBase != null) {
mCheckDataBase.close();
}
return mCheckDataBase != null;
}
private void copyDataBase() throws IOException {
final InputStream mInput = mContext.getAssets().open(DB_NAME);
final String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte[] mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer)) > 0) {
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
public boolean openDataBase() throws SQLException {
final String mPath = DB_PATH + DB_NAME;
mDataBase = SQLiteDatabase.openDatabase(mPath, null,
SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDataBase != null;
}
@Override
public synchronized void close() {
if (mDataBase != null)
mDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
`DBAdapter`
public class DBAdapter {
private static final String TAG = DBAdapter.class.getSimpleName();
private final Context mContext;
private SQLiteDatabase mDb;
private final DataBaseHelper mDbHelper;
public DBAdapter(Context context) {
this.mContext = context;
mDbHelper = new DataBaseHelper(mContext);
}
public DBAdapter createDatabase() throws SQLException {
try {
mDbHelper.createDataBase();
} catch (IOException mIOException) {
throw new Error("UnableToCreateDatabase");
}
return this;
}
public DBAdapter open() throws SQLException {
try {
mDbHelper.openDataBase();
mDbHelper.close();
mDb = mDbHelper.getReadableDatabase();
} catch (SQLException mSQLException) {
Log.e(TAG, mSQLException.toString());
throw mSQLException;
}
return this;
}
public void close() {
mDbHelper.close();
}
}
`Abhan` Extended Application Class
public class Abhan extends Application {
public static final String TAG = Abhan.class.getSimpleName();
public static final boolean DEBUG = true;
private int androidVersion = 4;
private DBAdapter dbAdapter = null;
@Override
public void onCreate() {
super.onCreate();
setAndroidVersion(android.os.Build.VERSION.SDK_INT);
if(dbAdapter == null) {
dbAdapter = new DBAdapter(getBaseContext());
dbAdapter.createDatabase();
}
}
public int getAndroidVersion() {
return androidVersion;
}
public void setAndroidVersion(int androidVersion) {
this.androidVersion = androidVersion;
}
public DBAdapter getDBInstatnce() {
dbAdapter.open();
return dbAdapter;
}
public void closeDataBase() {
dbAdapter.close();
if(DEBUG) {
android.util.Log.d(TAG, "DataBase closed.");
}
}
}
In your `AndroidManifest`, Declare `Abhan`
<application
android:name=".Abhan"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
In Your `Activity`, Access Your database using `Application` Class
private Abhan abhan;
In `onCreate`
abhan = (Abhan) this.getApplication();
Now access your database transaction method like this.
int currentDay = abhan.getDBInstatnce().getCurrentDay();
Here, `abhan.getDBInstatnce()` returns your `Database` instance which is single instance across your whole application and `getCurrentDay()` is my method, declared in `DBAdpater` which returns me a current day.
I hope this one can sort out your problem. Thanks.
Problem
I have an application uses sqlite db, at first install I check If database folder nor db file exists If not call updateDB function. but some cases for example on galaxy note 10.1 It gaves me error. on Load ; ``` this.dhn = DataHelper.getDataHelper(this); File directory = new File(Environment.getDataDirectory() + File.separator + "data" + File.separator + "XXX" + File.separator + "databases"); if(!directory.exists()) { directory.mkdirs(); updateDB(); } try { androidCheckout = this.dhn.Guid(); if(this.dhn.getSettings("dbVersion") == null || Integer.parseInt(this.dhn.getSettings("dbVersion")) != Version || !this.dhn.isTableExists("UserInfo")) { updateDB(); } } catch (SQLiteException e) { try { updateDB(); androidCheckout = this.dhn.Guid(); } catch (SQLiteException e11) { ManuelYukle(); } } public void updateDB() { this.dhn.close(); try { InputStream myInput; myInput = getAssets().open("XXX.db"); // Path to the just created empty db String outFileName = "/data/data/XXX/databases/" + "XXX.db"; // Open the empty db as the output stream FileOutputStream myOutput = new FileOutputStream(outFileName); // transfer bytes from the inputfile to the outputfile byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); buffer = null; outFileName = null; this.dhn.close(); this.dhn = null; this.dhn = DataHelper.getDataHelper(this); <<<<<<<< HERE IT CRUSHS } catch (IOException e1) { e1.printStackTrace(); } } ``` DBHELPER CLASS > ``` private static DataHelper singleton; public static DataHelper getDataHelper(Context context) { if (singleton == null) { singleton = new DataHelper(context); OpenHelper openHelper = new OpenHelper(singleton.context); singleton.db = openHelper.getWritableDatabase(); } if(!singleton.db.isOpen()){ OpenHelper openHelper = new OpenHelper(singleton.context); singleton.db = openHelper.getWritableDatabase(); } singleton.context = context; return singleton; } private DataHelper(Context context) { this.context = context; } ``` ERROR LOG FILE > ``` 12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database corruption at line 48171 of [ed759d5a9e], db=/data/data/XXX/databases/XXX_db 12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database disk image is malformed, db=/data/data/XXX/databases/XXX_db 12-09 19:11:15.772: E/SqliteDatabaseCpp(6271): sqlite3_exec - Failed to set synchronous mode = 1(Normal) 12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database corruption at line 48171 of [ed759d5a9e], db=/data/data/XXX/databases/XXX_db 12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database disk image is malformed, db=/data/data/XXX/databases/XXX_db 12-09 19:11:15.772: E/SqliteDatabaseCpp(6271): CREATE TABLE android_metadata failed 12-09 19:11:15.777: E/DefaultDatabaseErrorHandler(6271): Corruption reported by sqlite on database: /data/data/XXX/databases/XXX.db 12-09 19:11:15.782: E/DefaultDatabaseErrorHandler(6271): deleting the database file: /data/data/XXX/databases/XXX.db ```