2012-12-17 37 views
2

我想打開一個我創建並加載和/我的項目資產的sqlite數據庫。我使用一個類,MySQLiteHelper打開這個數據庫和處理升級等試圖打開/資產中的sqlite文件時收到「無法打開數據庫」錯誤

在我的活動我創建MySQLiteHelper的新實例......像我這樣做,它說,它不能打開數據庫(參見下面的logcat)。

有這個工作,現在停了下來。困惑爲什麼我現在收到此錯誤...我回滾了我的更改,但仍然收到此錯誤。我認爲它與我正在加載的文件有關?任何幫助,將不勝感激。

類開放源碼:

package com.sembasys....; 

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.SQLiteDatabase.CursorFactory; 
import android.database.sqlite.SQLiteException; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 

public class MySQLiteHelper extends SQLiteOpenHelper { 

    // The Android's default system path of your application database. 
    private static String DB_PATH = "/data/data/com.sembasys.metrosleepnyc/databases/"; 
    private static String DB_NAME = "metrosleep"; 

    private SQLiteDatabase myDataBase; 
    private final Context myContext; 
    private static final int DATABASE_VERSION = 1; 
    public static final String KEY_ID = "stop_id"; 
    public static final String LINE_ID = "line_id"; 
    public static final String STATION= "station_name"; 

    public MySQLiteHelper(Context context) { 
     super(context, DB_NAME, null, DATABASE_VERSION); 
     this.myContext = context; 
    } 

    /** 
    * Creates a empty database on the system and rewrites it with your own 
    * database. 
    * */ 
    public void createDataBase() throws IOException { 
     boolean dbExist = checkDataBase(); 
     if (dbExist) { 
      Log.v("DB Exists", "db exists"); 

      // By calling this method here onUpgrade will be called on a 
      // writeable database, but only if the version number has been 
      // bumped 
      this.getWritableDatabase(); 
     } 
     dbExist = checkDataBase(); 
     if (!dbExist) { 
      // 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(); 
      try { 
       copyDataBase(); 
      } catch (IOException e) { 
       throw new Error("Error copying database"); 
      } 
     } 
    } 

    /** 
    * Check if the database already exist to avoid re-copying the file each 
    * time you open the application. 
    * 
    * @return true if it exists, false if it doesn't 
    */ 
    private boolean checkDataBase() { 

     SQLiteDatabase checkDB = null; 

     try { 
      String myPath = DB_PATH + DB_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null, 
        SQLiteDatabase.OPEN_READONLY); 

     } catch (SQLiteException e) { 

      // database does't exist yet. 

     } 

     if (checkDB != null) { 

      checkDB.close(); 

     } 

     return checkDB != null ? true : false; 
    } 

    /** 
    * Copies your database from your local assets-folder to the just created 
    * empty database in the system folder, from where it can be accessed and 
    * handled. This is done by transfering bytestream. 
    * */ 
    private void copyDataBase() throws IOException { 

     // Open your local db as the input stream 
     InputStream myInput = myContext.getAssets().open(DB_NAME); 

     // Path to the just created empty db 
     String outFileName = DB_PATH + DB_NAME; 

     // Open the empty db as the output stream 
     OutputStream 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); 
     } 

     // Close the streams 
     myOutput.flush(); 
     myOutput.close(); 
     myInput.close(); 

    } 

    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) { 

    } 

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     if (newVersion > oldVersion) 
      Log.v("Database Upgrade", "Database version higher than old."); 
     myContext.deleteDatabase(DB_NAME); 
    } 

} 

活動在這裏我實現了上面的類:

package com.sembasys....; 


import com.actionbarsherlock.app.SherlockActivity; 
import android.widget.SimpleCursorAdapter; 
import android.annotation.TargetApi; 
import android.app.ListActivity; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase; 
import android.net.ConnectivityManager; 
import android.net.NetworkInfo; 
import android.os.Build; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.TextView; 

import android.support.v4.app.NavUtils; 

public class ChooseRoute extends ListActivity { 


    @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // Show the Up button in the action bar. 
     //getSupportActionBar().setDisplayHomeAsUpEnabled(true); 

     MySQLiteHelper myDbHelper = new MySQLiteHelper(null); 
     myDbHelper = new MySQLiteHelper(this); 


      try { 
       myDbHelper.openDataBase(); 
      }catch(SQLException sqle){ 
       throw sqle; 
      } 


     if(isNetworkAvailable()) { 

      setContentView(R.layout.activity_choose_route); 

      TextView empty = (TextView) findViewById(android.R.id.empty); 
      empty.setVisibility(View.VISIBLE); 

      SQLiteDatabase db = myDbHelper.getReadableDatabase(); 

      String TABLE_NAME = "Stops"; 
      Cursor cursor = db.query(true, TABLE_NAME , new String[] { MySQLiteHelper.LINE_ID, MySQLiteHelper.STATION}, null, null, null, null, null, null); 
      startManagingCursor(cursor); 
      String[] columns = new String[] { MySQLiteHelper.STATION }; 

      // the XML defined views which the data will be bound to 
      int[] to = new int[] { R.id.text }; 


      SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.todo_row, cursor, columns, to); 
      setListAdapter(adapter); 
      registerForContextMenu(getListView()); 


     } else { 

      setContentView(R.layout.no_connection); 

     } 


    } 

    private boolean isNetworkAvailable() { 
     ConnectivityManager connectivityManager 
       = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
     NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); 
     return activeNetworkInfo != null; 
    } 


} 

而且logcat的。

12-17 14:07:27.827: W/dalvikvm(23119): threadid=1: thread exiting with uncaught exception (group=0x40de8930) 
12-17 14:07:27.847: E/AndroidRuntime(23119): FATAL EXCEPTION: main 
12-17 14:07:27.847: E/AndroidRuntime(23119): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sembasys.metrosleepnyc/com.sembasys.metrosleepnyc.ChooseRoute}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.ActivityThread.access$600(ActivityThread.java:141) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.os.Handler.dispatchMessage(Handler.java:99) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.os.Looper.loop(Looper.java:137) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.ActivityThread.main(ActivityThread.java:5039) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at java.lang.reflect.Method.invokeNative(Native Method) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at java.lang.reflect.Method.invoke(Method.java:511) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at dalvik.system.NativeStart.main(Native Method) 
12-17 14:07:27.847: E/AndroidRuntime(23119): Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at com.sembasys.metrosleepnyc.MySQLiteHelper.openDataBase(MySQLiteHelper.java:126) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at com.sembasys.metrosleepnyc.ChooseRoute.onCreate(ChooseRoute.java:36) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.Activity.performCreate(Activity.java:5104) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080) 
12-17 14:07:27.847: E/AndroidRuntime(23119): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144) 
12-17 14:07:27.847: E/AndroidRuntime(23119): ... 11 more 
+1

我推薦'SQLiteAssetHelper'而不是滾動你自己的解決方案:https://github.com/jgilfelt/android-sqlite-asset-helper – CommonsWare

+0

爲什麼你將null傳遞給helper? MySQLiteHelper myDbHelper = new MySQLiteHelper(null); –

+0

@RobertEstivill它需要被定義。應該是(這個)而不是? – markbratanov

回答

2

根據你自己的代碼,openDatabase()查找在/databases文件夾中的數據庫,但數據庫仍處於/assets文件夾,直到您叫createDatabase()(或copyDatabase()直接)。在嘗試打開數據庫之前,您必須撥打createDataBase()將數據庫複製到適當的位置。

+0

這工作,謝謝!不過,我接受了@commonsWare的建議並實施了他提供的圖書館。 – markbratanov

相關問題