SQLiteAssetHelper NullPointerException sólo en algunos dispositivos
Estoy usando la biblioteca de SQLiteAssetHelper para tratar con mis operaciones del DB de la aplicación y está trabajando muy bien para casi cada teléfono que he probado con. Sin embargo, algunos usuarios con Android 2.3.3 – Informe 2.3.7 se bloquea cuando se realiza una llamada para abrir el db. Sospecho que esto se debe a algún problema que ocurre la primera vez que el db se está copiando de la carpeta de activos (como espacio insuficiente en el almacenamiento interno).
Clase de ayuda:
- Android / SQLite - Operación de bits en la cláusula WHERE
- ¿Cómo ejecutar la consulta en la base de datos SQLite en android?
- INSERTAR O IGNORAR tabla con la clave AUTOINCREMENT en Android
- ¿Cómo implementar deshacer un solo paso para los cambios en la base de datos SQLite?
- ¿Cuál es la sintaxis de "no igual" en SQLite?
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); } }
Clase del manejador (establezco un contador al tiempo de espera después de 10 si no se puede abrir el db):
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(); }
Clase de llamada:
private class DbAsyncTask extends AsyncTask<Long, Void, Void> { //... @Override protected Void doInBackground(Long... params) { dataHandler.open();
Excepción:
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)
- La base de datos SQLite de Android se corrompe
- SQLite Eliminar Cascade no funciona
- Seleccione la última fila
- Insertar matriz en la base de datos SQLite en android
- Abrir y editar archivos PDF en la aplicación de Android con API
- Ubicación de la base de datos sqlite en el dispositivo
- Android.database.sqlite.SQLiteException: no hay tal columna
- Consulta de base de datos de Android ContentProvider varias tablas
Posiblemente los usuarios han limpiado su almacenamiento o no tienen una tarjeta SD?
Probablemente lo que está pasando por accidentes esporádicos.
** ¿Ha implementado los métodos oncreate y onupgrade?
Yo uso el ayudante abierto. Así que nunca tengo problemas para abrir la base de datos.
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++; }
Buena suerte
Esta pregunta no tuvo una respuesta aceptada a pesar de que el PO indicó que se resolvía en los comentarios. Así que aquí está la respuesta:
No intente copiar la base de datos con un AsyncTask
que se llama de un método (como onCreate
) y, a continuación, intente rellenar un ListView
con datos de la base de datos en el mismo método. Si el AsyncTask
no ha terminado en el momento en que el ListView
necesita los datos, se generará una NullPointerException.
En su lugar, rellenar el ListView
desde el método onPostExecute
de AsyncTask
. Esto asegurará que la base de datos haya terminado de copiar.