2013-12-19 3 views
8

SQLiteAssetHelper 라이브러리를 사용하여 App 데이터베이스 작업을 처리하고 있으며 테스트를 거친 거의 모든 전화에서 정상적으로 작동합니다. 그러나 안드로이드 2.3.3 - 2.3.7을 가진 일부 사용자는 DB를 열려면 호출이 충돌합니다. 이 문제는 자산 폴더 (예 : 내부 저장소의 불충분 한 공간)에서 db가 처음 복사 될 때 발생합니다.SQLiteAssetHelper 일부 장치에서만 NullPointerException이 발생했습니다.

도우미 클래스 :

public class DbHelper extends SQLiteAssetHelper { 

    final static String DB_NAME="db"; 
    static final int DB_VERSION = 1307181213; 
    final Context context; 

    public DbHelper(Context c) { 
     super(c, DB_NAME, null, DB_VERSION); 
     this.context = c; 
     setForcedUpgradeVersion(DB_VERSION); 
    } 
} 

핸들러 클래스 (dB 열 수없는 경우 I는 10 초 후에 시간 초과 카운터를 설정) :

public class DbHandlerDao { 

    private SQLiteDatabase database; 
private DbHelper dbHelper; 

public DbHandlerDao(Context context) { 
    dbHelper = new DbHelper(context); 
} 

public void open() throws SQLException { 
    boolean opened = false; 
    int timeout = 0; 
    while (!opened && timeout < 10000) { 
     try { 
      database = dbHelper.getReadableDatabase(); 
      opened = true; 
     } 
     catch (IllegalStateException e) { 
      timeout += 500; 
      try { 
       Thread.sleep(500); 
      } catch (Exception e2) { 

      } 
     } 
    } 
} 

public void close() { 
    dbHelper.close(); 
} 

호출 클래스 :

private class DbAsyncTask extends AsyncTask<Long, Void, Void> { 

     //... 

     @Override 
     protected Void doInBackground(Long... params) { 
      dataHandler.open(); 

예외 :

java.lang.RuntimeException: An error occured while executing doInBackground() 
    at android.os.AsyncTask$3.done(AsyncTask.java:200) 
    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
    at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
    at java.lang.Thread.run(Thread.java:1019) 
Caused by: java.lang.NullPointerException 
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:180) 
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getReadableDatabase(SQLiteAssetHelper.java:257) 
    at com.example.DbHandlerDao.open(DbHandlerDao.java:25) 
    at com.example.SearchActivity$DbAsyncTask.doInBackground(SearchActivity.java:244) 
    at com.example.SearchActivity$DbAsyncTask.doInBackground(SearchActivity.java:1) 
    at android.os.AsyncTask$2.call(AsyncTask.java:185) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
+0

Android 4.3 및 4.4를 실행하는 여러 기기에서 동일한 버그가있는 것 같습니다. 이상한 점은 일관되게 재현 할 수 없다는 것입니다. – Ben

+0

github 프로젝트 자체에 문제로 게시 할 예정입니다. 라이브러리에 문제가있는 것이 거의 확실하기 때문에 표준 SQLiteOpenHelper에는이 문제가 없습니다. 다른 사람들도이 문제를 겪었던 것 같습니다 : https://github.com/jgilfelt/android-sqlite-asset-helper/issues/23 – anddev84

+2

고마워, 좋은 생각. 그러나 좀 더 조사한 후에, 나는 이것이 내 자신의 실수라는 것을 깨달았습니다. 긴 이야기를 간단히하기 위해, 나는 같은 데이터베이스를 사용하여'ListView'를 채우려고 시도한 액티비티의 onCreate 메소드에서 호출 된 AsyncTask에 데이터베이스를 복사했습니다. 내가'운이 좋았을 때만 작동하고'ListView'가 데이터베이스를 필요로하기 전에 백그라운드 작업이 끝났다고 밝혀졌습니다! – Ben

답변

0

아마도 사용자가 저장 용량을 삭제했거나 SD 카드가 없습니까?

아마 산발적 인 충돌이 발생합니다.

** oncreate 및 onupgrade 메소드를 구현 했습니까?

오픈 도우미를 사용합니다. 그래서 나는 데이터베이스를 여는 데 어려움을 겪지 않습니다.

public class RidesDatabaseHandler extends SQLiteOpenHelper { 

...

// Creating Tables 
@Override 
public void onCreate(SQLiteDatabase db) { 
    String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_RIDES + "(" 
      + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT," 
      + KEY_DESCRIPTION + " TEXT," + KEY_BOUNDS_NELAT + " TEXT," 
      + KEY_BOUNDS_NELONG + " TEXT," + KEY_BOUNDS_SWLAT + " TEXT," 
      + KEY_BOUNDS_SWLONG + " TEXT," + KEY_RESRAWID + " TEXT," 
      + KEY_RESDRAWABLEID + " TEXT," + KEY_PATH + " TEXT," 
      + " CONSTRAINT UNQ_" + KEY_PATH + " UNIQUE (" + KEY_PATH 
      + ") ON CONFLICT ABORT)"; 

    // VERSION 43 ADDS THE KEY_DATE_UPDATE COLUMN 
    CREATE_CONTACTS_TABLE += " , " + KEY_DATE_UPDATE + " INTEGER DEFAULT 0"; 

    db.execSQL(CREATE_CONTACTS_TABLE); 
} 

// Upgrading database 
@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

    int upgradeTo = oldVersion + 1; 
    while (upgradeTo <= newVersion) { 
     switch (upgradeTo) { 
     // update old resrawid's to constants 
     // this was caused when I saved R values in the database 
     // and then later realized they would change. 
     // the old resrawid is changed to a constant. 
     case 42: 
      ContentValues values; 
      @SuppressWarnings("unused") 
      // used for debugging so I can see the value of the update. 
      int res; 
      int rs; 
      rs = 2130968576; 
      values = new ContentValues(); 
      values.put(
        KEY_RESRAWID, 
        com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_DRAGON); 
      res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?", 
        new String[] { String.valueOf(rs) }); 

      rs = 2130968577; 
      values = new ContentValues(); 
      values.put(
        KEY_RESRAWID, 
        com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_M119); 
      res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?", 
        new String[] { String.valueOf(rs) }); 

      rs = 2130968578; 
      values = new ContentValues(); 
      values.put(
        KEY_RESRAWID, 
        com.gosylvester.bestrides.ImageTextListViewActivity.SAMPLE_MEDINA); 
      res = db.update(TABLE_RIDES, values, KEY_RESRAWID + " = ?", 
        new String[] { String.valueOf(rs) }); 
      break; 
     case 43: 
      // new column added for last_viewed. 
      db.execSQL(VERSION_43_ALTER); 
      break; 

     case 44: 
      // new index on KEY_DATE_UPDATE DESC 
      db.execSQL(VERSION_44_CREATE_INDEX); 
     } 
     upgradeTo++; 
    } 

행운은

0

이 질문은 영업 이익이 코멘트에 해결되었다 지적에도 불구하고 허용 대답이 없었다. 그래서 여기에 대한 대답입니다 :

방법에서 (예 : onCreate로)라고 한 후 동일한 방법으로 데이터베이스에서 데이터와 ListView을 채우기 위해 시도하는 AsyncTask로 데이터베이스를 복사하지 마십시오. ListView에 데이터가 필요한 시점까지 AsyncTask이 완료되지 않으면 NullPointerException이 발생합니다.

대신 onPostExecute 메서드에서 AsyncTaskListView을 채 웁니다. 그러면 데이터베이스가 복사를 완료합니다.

관련 문제