views:

81

answers:

1

I have four tabs (reports, review reports, map and settings). I have an sqlite database populated with report information. I wish to have the database accessible throughout the application. The reports tab successfully adds data to the database however using the same methodology crashes the application. The Android debugger points to the line where the database is called again.

In the reports tab the following code is used to launch the database...

this.reportDatabase = new ReportDatabase(this);
  this.reportDatabase.insert("(" + latitude + ", " + longitude + ", " + time + ", '" + spinnerState + "', " + lower + ", " + upper + ", " + agreed + ", " + getAlgorithmCount() + ", " + xAxis + ", " + yAxis + ", " + zAxis + ", " + altitude + ", "+ accuracy + ", 'photo');");

In the onCreate() method of the Review Tab - Where I wish to review reports - I try to access to the database through the call calling the return report method

this.reportDatabase = new ReportDatabase(this);

However this fails to work. In the android debugger highlights that the problem belongs with the context being provided to it. I realise that the report database has already been accessed by the report tab and wonder if this is causing the issue. I am new to programming android, the application is designed to report on flamingos in Africa, any help would be greatly appreciated!

Following the suggestion of Seva Alekseyev I have adapted as follows...

I have adapted my ReportDatabase as...

 public ReportDatabase(Context context) {
  super(context, DATABASE_NAME, null, DATABASE_VERSION);
  ReportDatabase.context = context;
  OpenHelper openHelper = new OpenHelper(ReportDatabase.context);
  this.database = openHelper.getWritableDatabase();
 }

 static ReportDatabase open(Context c){
  if(reportDatabase == null){
   reportDatabase = new ReportDatabase(ReportDatabase.context);
   return reportDatabase;
  }
  return reportDatabase;
 }

using...

 reportDatabase = ReportDatabase.open(this); 

As the call in both the report and review tab. Unfortunately this doesn't seem to work, the debugger stops on the same method. The full ReportDatabase.java file is here...

package com.android.flamingo;

import java.util.Vector;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class ReportDatabase extends SQLiteOpenHelper {
private static Context context;
private SQLiteDatabase database;

static ReportDatabase reportDatabase;

private static final String DATABASE_NAME = "flamingo_reports";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "reports";

/**
 * Default (and only) constructor....
 * 
 * @param context
 */

public ReportDatabase(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    ReportDatabase.context = context;
    OpenHelper openHelper = new OpenHelper(ReportDatabase.context);
    this.database = openHelper.getWritableDatabase();
}

static ReportDatabase open(Context c){
    if(reportDatabase == null){
        reportDatabase = new ReportDatabase(ReportDatabase.context);
        return reportDatabase;
    }
    return reportDatabase;
}

/**
 * 
 * @param name
 */

public void insert(String name){
    this.database.execSQL("INSERT INTO " + TABLE_NAME + "(latitude, longitude, time, lake, lower_estimate, higher_estimate, agreed_estimate, algorithm_count, xaxis, yaxis, zaxis, altitude, accuracy, photo_identifier) VALUES " + name);
}

/**
 * This method returns a double array and probably shouldn't be this hacky...
 * 
 * 
 * @return
 */

public Vector<ReportInstanceQuery> reportSelect(){
    Vector<ReportInstanceQuery> tempReports = new Vector<ReportInstanceQuery>();

    Cursor c = database.rawQuery("SELECT id,time,lake,lower_estimate,higher_estimate,agreed_estimate,algorithm_count FROM" + TABLE_NAME + ";",null);
    int indexTime = c.getColumnIndex("time");
    int indexLake = c.getColumnIndex("lake");
    int indexLowerEstimate = c.getColumnIndex("lower_estimate");
    int indexHigherEstimate = c.getColumnIndex("higher_estimate");
    int indexAgreedEstimate = c.getColumnIndex("agreed_estimate");
    int indexAlgorithmCount = c.getColumnIndex("algorithm_count");


    if (c != null){
        int i = 0;
        do {
            i++;
            int columnTime = c.getInt(indexTime);
            String columnLake = c.getString(indexLake);
            int columnLowerEstimate = c.getInt(indexLowerEstimate);
            int columnHigherEstimate = c.getInt(indexHigherEstimate);
            int columnAgreedEstimate = c.getInt(indexAgreedEstimate);
            int columnAlgorithmCount = c.getInt(indexAlgorithmCount);

            tempReports.add(new ReportInstanceQuery(columnTime, columnLake, columnLowerEstimate, columnHigherEstimate, columnAgreedEstimate, columnAlgorithmCount));
        } while (c.moveToNext());
    }
    reportDatabase.close();
    return tempReports;
}

/**
 * This method connects to the database  
 * 
 */

public void CSVReportSelect(){

}

public void delete(){
    this.database.delete(TABLE_NAME, null, null);
}

@Override
public void onCreate(SQLiteDatabase database) {        
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {      
}


private static class OpenHelper extends SQLiteOpenHelper {

    OpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY AUTOINCREMENT, latitude REAL, longitude REAL, time INTEGER, lake TEXT, lower_estimate INTEGER, higher_estimate INTEGER, agreed_estimate INTEGER, algorithm_count INTEGER, xaxis REAL, yaxis REAL, zaxis REAL, altitude REAL, accuracy REAL, photo_identifier TEXT)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w("Example", "Upgrading database, this will drop tables and recreate.");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }
}

}

With the error stack being...

ReportDatabase.(Context) line: 29 ReportDatabase.open(Context) line: 37
ReviewTab.onCreate(Bundle) line: 26 Instrumentation.callActivityOnCreate(Activity, Bundle) line: 1123
ActivityThread.performLaunchActivity(ActivityThread$ActivityRecord) line: 2231
ActivityThread.startActivityNow(Activity, String, Intent, ActivityInfo, IBinder, Bundle, Object) line: 2112 LocalActivityManager.moveToState(LocalActivityManager$LocalActivityRecord, int) line: 130
LocalActivityManager.startActivity(String, Intent) line: 342
TabHost$IntentContentStrategy.getContentView() line: 600
TabHost.setCurrentTab(int) line: 310
TabHost$2.onTabSelectionChanged(int, boolean) line: 126 TabWidget$TabClickListener.onClick(View) line: 268
RelativeLayout(View).performClick() line: 2183
RelativeLayout(View).onTouchEvent(MotionEvent) line: 3849
RelativeLayout(View).dispatchTouchEvent(MotionEvent) line: 3389 RelativeLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 831 TabWidget(ViewGroup).dispatchTouchEvent(MotionEvent) line: 863
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 863
TabHost(ViewGroup).dispatchTouchEvent(MotionEvent) line: 863
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 863
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 863
PhoneWindow$DecorView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 863
PhoneWindow$DecorView.superDispatchTouchEvent(MotionEvent) line: 1707
PhoneWindow.superDispatchTouchEvent(MotionEvent) line: 1197 HelloFlamingos(Activity).dispatchTouchEvent(MotionEvent) line: 1993 PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 1691
ViewRoot.handleMessage(Message) line: 1525
ViewRoot(Handler).dispatchMessage(Message) line: 99 Looper.loop() line: 123 ActivityThread.main(String[]) line: 3948
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 782
ZygoteInit.main(String[]) line: 540 NativeStart.main(String[]) line: not available [native method]

Ideas?

+1  A: 

You're trying to open the database several times. Use a single ReportDatabase object, available via a static method ReportDatabase. Something like this:

class ReportDatabase
{
    static ReportDatabase TheDatabase = null;

    static ReportDatabase Open(Context c)
    {
        if(TheDatabase == null)
            TheDatabase = new ReportDatabase(c);
        return TheDatabase;
    }
}

This is often called a singleton. Or a global :)

Seva Alekseyev
I have tried this, and it fails to work, do you have any further suggestions?
Mark Iliffe
Are you sure you're using ReportDatabase.open() throughout the app? Consider making the constructor private to check. If there are constructor calls out there, they will become compile errors.
Seva Alekseyev