En la aplicación en la que estoy trabajando, tuvimos una migración manual compleja que requería análisis de datos, comandos SQL manuales, etc. Esto fue para convertir una columna List<X> en una nueva tabla vinculada de X Anteriormente escribí sobre el enfoque, pero los comandos específicos no son especialmente relevantes para esta pregunta.
El problema que encuentro es que aproximadamente el 1 % de los usuarios experimentan un bloqueo como parte de esta migración. Esto no se puede reproducir en las pruebas y, debido al tamaño de nuestra tabla, Crashlytics no puede mostrar ningún error útil:
La pérdida de datos de los clientes no es catastrófica en este contexto, pero estar atrapado en el ciclo actual de "intentar migrar, bloquear, reabrir la aplicación y repetir" sí lo es. Como tal, solo quiero renunciar a la migración y recurrir a una migración destructiva si encontramos una excepción.
¿Alguna idea de cómo se puede hacer esto? Mi solución actual es volver a ejecutar los cambios de la base de datos (pero no la migración de datos presumiblemente fallida) dentro de catch , pero esto se siente muy extraño.
Nuestra base de datos se define como:
Room.databaseBuilder( context.applicationContext, CreationDatabase::class.java, "creation_database" ) .addMigrations(MIGRATION_11_12, MIGRATION_14_15) .fallbackToDestructiveMigration() .build() donde MIGRATION_14_15 es:
private val MIGRATION_14_15 = object : Migration(14, 15) { override fun migrate(database: SupportSQLiteDatabase) { try { // database.execSQL create table etc } catch (e: Exception) { e.printStackTrace() // Here is where I want to give up, and start the DB from scratch } } }El problema que tiene es que no puede (al menos fácilmente) invocar el respaldo, ya que solo se invoca cuando no hay migración.
Lo que podría hacer es imitar lo que hace el retroceso (muy cerca de lo que hace). Esa es la alternativa que eliminará (creo) el archivo de la base de datos y creará la base de datos desde cero y luego invocará el método createAllTables de las bases de datos _Impl (java generada).
Sin embargo, es probable que tenga problemas si elimina el archivo ya que la conexión de la base de datos se ha pasado a la migración.
Entonces, en su lugar, podría DROP todas las tablas de la aplicación usando el código copiado del método dropAllTables del java. Luego podría seguir esto con el código del método createAllTables .
El gotcha , es que la excepción 
(Esperado.... Encontrado....) que ha mostrado NO está dentro de la migración sino después de la migración cuando Room está tratando de construir la base de datos, por lo que no tiene control/lugar para hacer la imitación alternativa anterior a menos que esto se hizo para todas las migraciones 14-15.
Quizás lo que podría hacer es atrapar la excepción, presentar un cuadro de diálogo solicitando al usuario que desinstale la aplicación y luego la vuelva a instalar. Esto evitaría la migración, ya que sería una instalación nueva.