2013-09-05 2 views
0

나는 안드로이드에 대한 정보를 SQLite 데이터베이스에 저장하는 안드로이드를 개발했습니다. 모든 것이 내 4.0.3 전화 및 4.0.3 AVD에서 제대로 작동하는 것으로 보이지만 Jelly Bean 및 최신 버전에서도 작동하고 싶습니다. 응용 프로그램은 정말 아무것도 매우 복잡한 일을하지 않습니다. (http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html) 내가 어떻게 든 인스턴스 문제가 있다고 생각 구글에서 내 초기 검색에서안드로이드 애플 리케이션 SQLite와 ICS에서 실행하지만 젤리가 실행되지 않습니다 - IllegalStateException

09-05 01:45:40.311: W/dalvikvm(1062): threadid=1: thread exiting with uncaught exception >(group=0x414c4700) 09-05 01:45:40.331: E/AndroidRuntime(1062): FATAL EXCEPTION: main 09-05 01:45:40.331: E/AndroidRuntime(1062): java.lang.RuntimeException: Unable to start >activity ComponentInfo{ard.util.fueltracker/ard.util.fueltracker.TitleScreenActivity}: >java.lang.IllegalStateException: attempt to re-open an already-closed object: >SQLiteDatabase: /data/data/ard.util.fueltracker/databases/vehicleDatabase 09-05 01:45:40.331: E/AndroidRuntime(1062): at >android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)

, 그래서 여기에 접근 # 1을 따라 : 나는 에뮬레이트 된 젤리 콩 장치에 응용 프로그램을 불 때 나는 치명적인 예외 오류가 발생 , 그러나 이것은 차이를 만드는 것처럼 보이지 않습니다. 변경 사항이있는 ICS에서도 여전히 작동합니다.

package ard.util.fueltracker; 

import java.util.List; 

import ard.util.fueltracker.util.SystemUiHider; 

import android.annotation.SuppressLint; 
import android.annotation.TargetApi; 
import android.app.Activity; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.Handler; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.Window; 
import android.view.WindowManager; 
import android.content.Intent; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemSelectedListener; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.Spinner; 
import android.widget.Toast; 

/** 
* An example full-screen activity that shows and hides the system UI (i.e. 
* status bar and navigation/system bar) with user interaction. 
* 
* @see SystemUiHider 
*/ 
@SuppressLint("NewApi") 
public class TitleScreenActivity extends Activity implements OnItemSelectedListener { 
    /** 
    * Whether or not the system UI should be auto-hidden after 
    * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds. 
    */ 
    private static final boolean AUTO_HIDE = false; 

    /** 
    * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after 
    * user interaction before hiding the system UI. 
    */ 
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000; 

    /** 
    * If set, will toggle the system UI visibility upon interaction. Otherwise, 
    * will show the system UI visibility upon interaction. 
    */ 
    private static final boolean TOGGLE_ON_CLICK = false; 

    /** 
    * The flags to pass to {@link SystemUiHider#getInstance}. 
    */ 
    //private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION; 
    private static final int HIDER_FLAGS = 0; 

    /** 
    * The instance of the {@link SystemUiHider} for this activity. 
    */ 
    private SystemUiHider mSystemUiHider; 

    // Spinner element 
    Spinner spinner; 

    // Buttons 
    Button btnAdd; 
    Button btnLogo; 


    @SuppressLint("NewApi") 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     getWindow().requestFeature(Window.FEATURE_ACTION_BAR); //new 
     getActionBar().hide();         //new 
     getWindow().setFlags(
      WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     setContentView(R.layout.activity_title_screen); 

     // Spinner element 
     spinner = (Spinner) findViewById(R.id.titleSelectionSpinner); 

     // buttons 
     btnAdd = (Button) findViewById(R.id.button_go); 
     btnLogo = (Button) findViewById(R.id.button_ard_logo); 

     // Spinner click listener 
     spinner.setOnItemSelectedListener(this); 

     // Check for Add New Vehicle entry to create menu option in drop down list 
     checkAddNewVehicle(); 

     // Loading spinner data from database 
     loadSpinnerData();  

     //"Go" button actions 
     btnAdd.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View arg0) { 
       //Starting a new Intent 
       Intent screenAddVehicle = new Intent(getApplicationContext(), AddVehicleActivity.class); 
       Intent screenRecordViewing = new Intent(getApplicationContext(), RecordViewing.class); 
       String SpinnerChoice = spinner.getSelectedItem().toString(); 

       //Sending data to another Activity 
       //store value of vehicle label for Record Viewing screen 
       screenRecordViewing.putExtra("vehicleLabel", SpinnerChoice); 

       //interpret Spinner choice as Menu items 
       //"Add New Vehicle" always at Position 0 
       if (SpinnerChoice == spinner.getItemAtPosition(0).toString()) { 
       startActivity(screenAddVehicle); 
       } else { 
        //display value of selection if not "Add New Vehicle" 
        //Toast.makeText(spinner.getContext(), "Selection:" + SpinnerChoice, Toast.LENGTH_LONG).show(); 

        //go to Record Viewing screen 
        startActivity(screenRecordViewing); 
       } 

      } 
     }); 

     //"Logo" button - display program copyright 
     btnLogo.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View arg0) { 
       Toast.makeText(getApplicationContext(), "FuelTracker is Copyright 2013 by Authentic Ruby Designs", Toast.LENGTH_LONG).show(); 
      } 


     }); 

     final View controlsView = findViewById(R.id.fullscreen_content_controls); 
     final View contentView = findViewById(R.id.fullscreen_content); 

     // Set up an instance of SystemUiHider to control the system UI for 
     // this activity. 
     mSystemUiHider = SystemUiHider.getInstance(this, contentView, 
       HIDER_FLAGS); 
     mSystemUiHider.setup(); 
     mSystemUiHider 
       .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() { 
        // Cached values. 
        int mControlsHeight; 
        int mShortAnimTime; 

        @Override 
        @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 
        public void onVisibilityChange(boolean visible) { 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { 
          // If the ViewPropertyAnimator API is available 
          // (Honeycomb MR2 and later), use it to animate the 
          // in-layout UI controls at the bottom of the 
          // screen. 
          if (mControlsHeight == 0) { 
           mControlsHeight = controlsView.getHeight(); 
          } 
          if (mShortAnimTime == 0) { 
           mShortAnimTime = getResources().getInteger(
             android.R.integer.config_shortAnimTime); 
          } 
          controlsView 
            .animate() 
            .translationY(visible ? 0 : mControlsHeight) 
            .setDuration(mShortAnimTime); 
         } else { 
          // If the ViewPropertyAnimator APIs aren't 
          // available, simply show or hide the in-layout UI 
          // controls. 
          controlsView.setVisibility(visible ? View.VISIBLE 
            : View.GONE); 
         } 

         if (visible && AUTO_HIDE) { 
          // Schedule a hide(). 
          delayedHide(AUTO_HIDE_DELAY_MILLIS); 
         } 
        } 
       }); 

     // Set up the user interaction to manually show or hide the system UI. 
     contentView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       if (TOGGLE_ON_CLICK) { 
        mSystemUiHider.toggle(); 
       } else { 
        mSystemUiHider.show(); 
       } 
      } 
     }); 

     // Upon interacting with UI controls, delay any scheduled hide() 
     // operations to prevent the jarring behavior of controls going away 
     // while interacting with the UI. 
     findViewById(R.id.button_go).setOnTouchListener(
       mDelayHideTouchListener); 
    } 

    @Override 
    protected void onPostCreate(Bundle savedInstanceState) { 
     super.onPostCreate(savedInstanceState); 

     // Trigger the initial hide() shortly after the activity has been 
     // created, to briefly hint to the user that UI controls 
     // are available. 
     //delayedHide(100); 
    } 

    /** 
    * Touch listener to use for in-layout UI controls to delay hiding the 
    * system UI. This is to prevent the jarring behavior of controls going away 
    * while interacting with activity UI. 
    */ 
    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent motionEvent) { 
      if (AUTO_HIDE) { 
       delayedHide(AUTO_HIDE_DELAY_MILLIS); 
      } 
      return false; 
     } 
    }; 

    Handler mHideHandler = new Handler(); 
    Runnable mHideRunnable = new Runnable() { 
     @Override 
     public void run() { 
      mSystemUiHider.hide(); 
     } 
    }; 

    /** 
    * Schedules a call to hide() in [delay] milliseconds, canceling any 
    * previously scheduled calls. 
    */ 
    private void delayedHide(int delayMillis) { 
     mHideHandler.removeCallbacks(mHideRunnable); 
     mHideHandler.postDelayed(mHideRunnable, delayMillis); 
    } 
    @Override 
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, 
      long arg3) { 
     // TODO Auto-generated method stub 

    } 
    @Override 
    public void onNothingSelected(AdapterView<?> arg0) { 
     // TODO Auto-generated method stub 

    } 

    /** 
    * Function to check that Add New Vehicle is the first label in the DB table 
    */ 
    private void checkAddNewVehicle() { 
     // database handler 
     //DatabaseHandler db = new DatabaseHandler(getApplicationContext()); 
     DatabaseHandler db = DatabaseHandler.getInstance(getApplicationContext()); 

     // table data 
     List<String> labels = db.getAllLabels(); 

     //Check for "Add New Vehicle" entry at first row of table 
     if (labels.isEmpty()) { 
      db.insertLabel("Add New Vehicle"); 
     } 
    } 

    /** 
    * Function to load the spinner data from SQLite database 
    * */ 
    private void loadSpinnerData() { 
     // database handler 
     //DatabaseHandler db = new DatabaseHandler(getApplicationContext()); 
     DatabaseHandler db = DatabaseHandler.getInstance(getApplicationContext()); 

     // Spinner Drop down elements 
     List<String> labels = db.getAllLabels(); 


     // Creating adapter for spinner 
     ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, 
       android.R.layout.simple_spinner_item, labels); 

     // Drop down layout style - list view with radio button 
     dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 

     // attaching data adapter to spinner 
     spinner.setAdapter(dataAdapter); 
    } 



} 

그리고 여기 내 DatabaseHandler 클래스의 : 여기

내 TitleScreenActivity의 코드입니다 그것의 일부는 아마 추한 모습

package ard.util.fueltracker; 

import java.text.DecimalFormat; 
import java.util.ArrayList; 
import java.util.List; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.widget.TableLayout; 

public class DatabaseHandler extends SQLiteOpenHelper { 
    //create static instance 
    private static DatabaseHandler mInstance = null; 

    // Database Version 
    private static final int DATABASE_VERSION = 1; 

    // Database Name 
    private static final String DATABASE_NAME = "vehicleDatabase"; 

    // Labels table name 
    private static final String TABLE_LABELS = "labels"; 

    // Fuel Data table name 
    private static final String TABLE_FUELDATA = "fuel_data"; 

    // Labels Table Columns names 
    private static final String KEY_ID = "id"; 
    private static final String KEY_NAME = "name"; 

    // Fuel Data Tables Columns names 
    private static final String KEY_ENTRY = "entry_id"; 
    private static final String FIELD_VEHICLEID = "vehicle_id"; 
    private static final String FIELD_DATE = "date"; 
    private static final String FIELD_FTYPE = "fuel_type"; 
    private static final String FIELD_BRAND = "brand"; 
    private static final String FIELD_PRICE = "price"; 
    private static final String FIELD_KMS = "kms"; 
    private static final String FIELD_LITRES = "litres"; 
    private static final String FIELD_LPER = "l_per"; 
    private static final String FIELD_MPG = "mpg"; 
    // Fuel Data Columns for display - query shorthand 
    private static final String[] fuelDataDisplayCols = { FIELD_DATE, FIELD_FTYPE, FIELD_BRAND, FIELD_PRICE, 
     FIELD_KMS, FIELD_LITRES, FIELD_LPER, FIELD_MPG }; 

    public static DatabaseHandler getInstance(Context ctx) { 
     //Use the application context to avoid leaking Activity's context 
     if (mInstance == null) { 
      mInstance = new DatabaseHandler(ctx.getApplicationContext()); 
     } 
     return mInstance; 
    } 

    private DatabaseHandler(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    // Creating Tables 
    @Override 
    public void onCreate(SQLiteDatabase db) { 
     // Category table create query 
     String CREATE_CATEGORIES_TABLE = "CREATE TABLE " + TABLE_LABELS + "(" 
       + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT)";   
     db.execSQL(CREATE_CATEGORIES_TABLE); 

     // Fuel Data table create query 
     String CREATE_FUELDATA_TABLE = "CREATE TABLE " + TABLE_FUELDATA + "(" 
       + KEY_ENTRY + " INTEGER PRIMARY KEY," + FIELD_VEHICLEID + " INTEGER," 
       + FIELD_DATE + " TEXT," + FIELD_FTYPE + " TEXT," + FIELD_BRAND + 
       " TEXT," + FIELD_PRICE + " REAL," + FIELD_KMS + " REAL," 
       + FIELD_LITRES + " REAL," + FIELD_LPER + " REAL," + FIELD_MPG + 
       " REAL)"; 
     db.execSQL(CREATE_FUELDATA_TABLE); 
     db.close(); 

    } 

    // Upgrading database 
    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // Drop older table if existed 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_LABELS); 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_FUELDATA); 

     // Create tables again 
     onCreate(db); 
    } 

    /** 
    * Inserting new label into Labels table 
    * */ 
    public void insertLabel(String label){ 
     SQLiteDatabase db = this.getWritableDatabase(); 

     ContentValues values = new ContentValues(); 
     values.put(KEY_NAME, label); 

     // Inserting Row 
     db.insert(TABLE_LABELS, null, values); 
     db.close(); // Closing database connection 
    } 

    /** 
    * Inserting entry data into Fuel Data table 
    */ 
    //public void insertFuelData(int vehicleID, String date, String ftype, String brand, 
    //  float price, float kms, float litres) { 
    public void insertFuelData(ArrayList<String> fuelEntryData) { 
     SQLiteDatabase dbWrite = this.getWritableDatabase(); 
     ArrayList<String> fuelEntry = fuelEntryData; 
     ContentValues values = new ContentValues(); 

     //turn array values into individual field values with correct datatype 
     int vehicleID = getVehicleID(fuelEntry.get(0)); 
     String date = fuelEntry.get(1); 
     String ftype = fuelEntry.get(2); 
     String brand = fuelEntry.get(3); 
     double price = Double.parseDouble((fuelEntry.get(4))); 
     double kms = Double.parseDouble((fuelEntry.get(5))); 
     double litres = Double.parseDouble((fuelEntry.get(6)));  

     //values for calculations 
     double lper; 
     double mpg; 
     //Format calculations to round to one significant digit 
     DecimalFormat df = new DecimalFormat("###.#"); 

     //calculate Liters/100Kilometres 
     lper = (100/(kms/litres)); 
     //calculate U.S. Miles Per Gallon 
     mpg = (kms/litres) * 2.35; 

     //Prepare data and Insert row into table 
     values.put(FIELD_VEHICLEID, vehicleID); 
     values.put(FIELD_DATE, date); 
     values.put(FIELD_FTYPE, ftype); 
     values.put(FIELD_BRAND, brand); 
     values.put(FIELD_PRICE, price); 
     values.put(FIELD_KMS, kms); 
     values.put(FIELD_LITRES, litres); 
     values.put(FIELD_LPER, df.format(lper)); 
     values.put(FIELD_MPG, df.format(mpg)); 

     dbWrite.insert(TABLE_FUELDATA, null, values); 
     dbWrite.close();   

    } 

    /** 
    * Getting all labels 
    * returns list of labels 
    * */ 
    public List<String> getAllLabels(){ 
     List<String> labels = new ArrayList<String>(); 

     // Select All Query 
     String selectQuery = "SELECT * FROM " + TABLE_LABELS; 

     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cursor = db.rawQuery(selectQuery, null); 

     // looping through all rows and adding to list 
     if (cursor.moveToFirst()) { 
      do { 
       labels.add(cursor.getString(1)); 
      } while (cursor.moveToNext()); 
     } 

     // closing connection 
     cursor.close(); 
     db.close(); 

     // returning lables 
     return labels; 
    } 

    /** 
    * Get entries based on vehicle id 
    */ 
    public List<List<String>> getFuelData(int vehicleID) { 

     //List of Lists - each row/entry of data is a separate List 
     List<List<String>> fuelDataTable = new ArrayList<List<String>>(); 
     List<String> fuelDataRow = new ArrayList<String>(); 

     //Select Query 
     String selectQuery = "SELECT * FROM " + TABLE_FUELDATA + 
       " WHERE vehicle_id = ? "; 

     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cursor = db.rawQuery(selectQuery, new String[] { String.valueOf(vehicleID) }); 

     // looping through all rows and 9 columns (not incl key) and adding to list 
     if (cursor.moveToFirst()) { 
      do { 
       for(int i = 1; i < 10; i++) { 
        //doesn't work with non-string values 
        //fuelDataRow.add(cursor.getString(i)); 
       } 
       //add each row in its entirety to the List; multi-dimenionsal list 
       fuelDataTable.add(fuelDataRow); 
       //empty fuelDataRow 
       fuelDataRow.clear(); 
      } while (cursor.moveToNext()); 
     } 

     // closing connection 
     cursor.close(); 
     db.close(); 

     //return data 
     return fuelDataTable; 
    } 

    public List<String> getFuelDataRows(int vehicleID) { 
     List<String> fuelDataTable = new ArrayList<String>(); 
     SQLiteDatabase db = this.getReadableDatabase(); 

     //Get data from database table 
     Cursor c = db.query(TABLE_FUELDATA, fuelDataDisplayCols, " vehicle_id=? ", new String[] { String.valueOf(vehicleID) }, null, null, FIELD_DATE); 

     //Insert Header row into Array 
     fuelDataTable.add("Date"); 
     fuelDataTable.add("Type"); 
     fuelDataTable.add("Brand"); 
     fuelDataTable.add("Price"); 
     fuelDataTable.add("KMs"); 
     fuelDataTable.add("Litres"); 
     fuelDataTable.add("L/100"); 
     fuelDataTable.add("MPG"); 

     //Go to beginning of Cursor data and loop through 
     c.moveToFirst(); 
     while (!c.isAfterLast()) { 
      //add each cell in the row to List array  
      fuelDataTable.add(c.getString(c.getColumnIndex(FIELD_DATE))); 
      fuelDataTable.add(c.getString(c.getColumnIndex(FIELD_FTYPE))); 
      fuelDataTable.add(c.getString(c.getColumnIndex(FIELD_BRAND))); 
      fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_PRICE)))); 
      fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_KMS)))); 
      fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_LITRES)))); 
      fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_LPER)))); 
      fuelDataTable.add(String.valueOf(c.getDouble(c.getColumnIndex(FIELD_MPG)))); 
      c.moveToNext(); 
     } 
     // Make sure to close the cursor 
     c.close(); 
     db.close(); 

     return fuelDataTable; 
    } 


    public int getVehicleID(String label) { 
     // set variables 
     SQLiteDatabase dbReader = this.getReadableDatabase(); 
     String vLabel = label; 


     //Query String 
     String selectQuery = "SELECT " + KEY_ID + " FROM " + TABLE_LABELS + 
       " WHERE name = ? "; 
     Cursor c = dbReader.rawQuery(selectQuery, new String[] { vLabel }); 

     //avoid out of bounds exception 
     c.moveToFirst();   

     //extract value as integer 
     int vID = c.getInt(c.getColumnIndex(KEY_ID)); 
     c.close(); 
     return vID; 
    } 
} 

- 이것이 내 첫 번째 응용 프로그램 프로젝트와 이클립스 자동으로 입력 일부 창조의 방법의 - 그러나 그것은 아이스크림 샌드위치에서 잘 작동하고 있습니다.

모든 단서를 보내 주셔서 감사합니다.

답변

0

db.close()public void onCreate()에 필요하지 않습니다. 아마도 문제가 해결 될 것입니다.

+0

그게 전부 였어! 그렇게 간단한 솔루션 이었기 때문에 기쁩니다. 원래 ICS 기계에서 계속 작동하지만 새로운 Jellybean에서는 작동하지 않는 특별한 이유가 있습니까? 그것은 OS 때문입니까 아니면 에뮬레이터 소프트웨어 때문입니까? – mrmacross

+0

잘 모르겠지만, onCreate (db), onUpgrade() 등의 메소드를 아는 한 데이터베이스 객체를 params로받는 곳과 같이, 프레임 워크가 명시 적으로 db를 닫을 필요가 없습니다. 이. – Varun

관련 문제