2012-12-17 4 views
2

프로젝트의/assets 및/sqlite 데이터베이스를 열려고합니다. 나는 그래서, 그것은 그가 수 없다고 않는 한 내가 ... MySQLiteHelper의 새 인스턴스를 만들 내 활동 등/assets에서 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; 
    } 


} 

그리고 로그 캣

클래스 sqlite가를 엽니 다.

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을 전달합니까? MySQLiteHelper myDbHelper = 새로운 MySQLiteHelper (null); –

+0

@RobertEstivill 정의가 필요했습니다. 대신 (this)이되어야합니까? – markbratanov

답변

2

는 자신의 코드에 따르면, openDatabase()/databases 폴더 데이터베이스를 검색하지만 createDatabase() (또는 copyDatabase() 직접)를 호출 할 때까지 데이터베이스가 /assets 폴더에 아직도있다. 데이터베이스를 열려고 시도하기 전에 데이터베이스를 적절한 위치로 복사하려면 createDataBase()으로 전화해야합니다.

+0

감사합니다. 그러나 저는 @commonsWare 조언을 받아 그가 제공 한 라이브러리를 구현했습니다. – markbratanov

관련 문제