I have been working on a way to pass a reference between Activities, to my DataBaseHelper class. I don’t want to recreate new instances of DataBaseHelper in each new activity.
From what I have seen, the best way to do this is to implement android.os.parcelable, which is fine.
However, when I try to override the DataBaseHelper constructor with:
public DataBaseHelper(Parcel source)
I get an error telling me that the constructor is undefined.
I kind of understand what this means, but am not sure how to get around this issue and so implement Parcelable in this class.
Below is the DatabaseHelper class, the parcelable code is towards the bottom.
package com.drager;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
public class DataBaseHelper extends SQLiteOpenHelper implements Parcelable{
//private static String DB_PATH = "/data/data/com.drager/databases/";
private static String DB_PATH = Environment.getDataDirectory()+"/data/com.drager/databases/";
final static String DB_NAME = "myDBName";
private SQLiteDatabase myDataBase=null;
private final Context myContext;
private DataBaseHelper myDbHelper;
private static String TAG ="MyActivity";
public DataBaseHelper(Context context){
super(context, DB_NAME, null, 1);
this.myContext = context;
}
public DataBaseHelper(Parcel source) {
super(source);
// TODO Auto-generated constructor stub
}
public DataBaseHelper createDataBase() throws IOException{
boolean dbExist =checkDataBase();
//SQLiteDatabase db_read =null;
Log.i(TAG,"############value of dbExist"+dbExist+"##########");
if (dbExist){
copyDataBase();
//db must exist
}
else{
myDbHelper = new DataBaseHelper(myContext);
myDataBase = myDbHelper.getReadableDatabase();
myDataBase.close();
//this.getReadableDatabase();
//db_read.close();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("error copying database");
}
}
return this;
}
public Cursor executeStatement(){
Log.i(TAG,"in execute statement");
Cursor cursor=null;
cursor=myDataBase.rawQuery("SELECT _ID, title, value "+
"FROM constants ORDER BY title",
null);
return cursor;
}
public String[] getTextViewItem(){
Cursor cursor=null;
String str="";
String[] resultsString;
//store query results in cursor
cursor=myDataBase.rawQuery("SELECT shrt_description FROM description",
null);
ArrayList strings = new ArrayList();
for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
str =cursor.getString(cursor.getColumnIndex("shrt_description"));
strings.add(str);
}
resultsString =(String[])strings.toArray(new String[strings.size()]);
close();//close database after use
return resultsString;
}
public String[] getDetailedDescription(){
Cursor cursor=null;
String str="";
String[] resultsString;
//store query results in cursor
cursor=myDataBase.rawQuery("SELECT detailed_description FROM description",
null);
ArrayList strings = new ArrayList();
for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
str =cursor.getString(cursor.getColumnIndex("detailed_description"));
strings.add(str);
}
resultsString =(String[])strings.toArray(new String[strings.size()]);
close();//close database after use
return resultsString;
}
public void copyDataBase() throws IOException{
// open db as input stream
InputStream myInput;
//open empty db as output stream
OutputStream myOutPut;
try {
myInput = myContext.getAssets().open(DB_NAME);
//path to newly created db
String outFileName =DB_PATH + DB_NAME;
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();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
String myPath = DB_PATH + DB_NAME;
try {
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLException e) {
e.printStackTrace();
return false;
}
if (checkDB != null){
checkDB.close();
}
return true;
//return checkDB !=null ? true : false;
}
public void openDataBase()throws SQLException{
//open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
@Override
public synchronized void close(){
if(myDataBase != null){
myDataBase.close();
}
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeParcelable((Parcelable) myDataBase, 0);
dest.writeString(DB_PATH);
dest.writeString(DB_NAME);
dest.writeString(TAG);
dest.writeParcelable((Parcelable) myContext, 0);
dest.writeParcelable(myDbHelper, 0);
}
public static final Parcelable.Creator<DataBaseHelper> CREATOR = new Parcelable.Creator<DataBaseHelper>() {
@Override
public DataBaseHelper createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new DataBaseHelper(source);
}
@Override
public DataBaseHelper[] newArray(int size) {
// TODO Auto-generated method stub
return null;
}
};
}
Any help greatly appreciated.
Thanks in advance.
You seem to be unnecessarily complicating things. You say:
But restoring a DataBaseHelper object from a Parcel does create a new instance of the DataBaseHelper class; it’s just a harder way of doing it than creating a fresh DataBaseHelper.
In any case, although you didn’t copy and paste the error message here, I think I know what error you received: It’s not that your
DataBaseHelperclass doesn’t contain the right constructor; it does. It’s that the super class,SQLiteOpenHelper, doesn’t implementParcelable. The only way around this problem would be to manage all of theSQLiteOpenHelper‘s state yourself. That is, include the SQLiteOpenHelper’s state as part of your implementation ofwriteToParcel, and restore that state as part ofDatabaseHelper(Parcel). The constructor then would call the default constructor forSQLiteOpenHelper. The resulting constructor would look something like this:I don’t think it’s likely to be worth the effort, but that’s up to you to decide.