2013-12-19 7 views
8

私のAppDB操作に対処するためにSQLiteAssetHelperライブラリを使用しています。テストしたほぼすべての電話機で正常に動作しています。しかし、Android 2.3.3 - 2.3.7のユーザーの中には、データベースを開くための呼び出しが行われたときにクラッシュするものがあります。これは、データベースが資産フォルダからコピーされて初めて(内部ストレージのスペース不足など)何らかの問題が発生したためです。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); 
    } 
} 

ハンドラ・クラス(デシベルを開くことができない場合、私は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

ありがとう、良いアイデア。しかし、もう少し調査した後、私はこれが自分の間違いであることに気付きました。長い話をするには、アクティビティの 'onCreate'メソッドから呼び出された' AsyncTask'でデータベースをコピーしていましたが、そのデータベースは同じデータベースを使って 'ListView'にポピュレートしようとしました。それは、私が運が良かったときに働いただけで、バックグラウンドタスクは、 '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

この質問は、OPは、それがコメントで解決したことを示しているにもかかわらず、受け入れ答えを持っていませんでした。

は(例えばonCreateなど)メソッドから呼び出され、その後、同じ方法でデータベースからのデータでListViewを投入しようとしているAsyncTaskでデータベースをコピーしようとしないでください:だからここに答えがあります。 ListViewがデータを必要とする時点までにAsyncTaskが終了していない場合は、NullPointerExceptionが発生します。

代わりにonPostExecuteメソッドAsyncTaskからListViewを入力してください。これにより、データベースのコピーが確実に完了します。

関連する問題