Room: el directorio de exportación de esquema no se proporciona al procesador de anotaciones, por lo que no podemos exportar el esquema

350

Estoy usando la sala de componentes de la base de datos de Android

He configurado todo, pero cuando compilo, Android Studio me da esta advertencia:

El directorio de exportación de esquema no se proporciona al procesador de anotaciones, por lo que no podemos exportar el esquema. Puede proporcionar room.schemaLocationun argumento del procesador de anotaciones O establecer exportSchema en falso.

Según tengo entendido, es la ubicación donde se ubicará el archivo DB

¿Cómo puede afectar mi aplicación? ¿Cuál es la mejor práctica aquí? ¿Debo usar la ubicación predeterminada ( falsevalor)?

Misha Akopov
fuente

Respuestas:

396

Según los documentos :

Puede configurar el argumento del procesador de anotaciones (room.schemaLocation) para indicarle a Room que exporte el esquema a una carpeta. Aunque no es obligatorio, es una buena práctica tener el historial de versiones en su base de código y debe enviar ese archivo a su sistema de control de versiones (¡pero no lo envíe con su aplicación!).

Entonces, si no necesita verificar el esquema y desea deshacerse de la advertencia, simplemente agregue exportSchema = falsea su RoomDatabase, de la siguiente manera.

@Database(entities = { YourEntity.class }, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
   //...
}

Si sigue la respuesta de @mikejonesguy a continuación, seguirá las buenas prácticas mencionadas en los documentos :). Básicamente obtendrá un .jsonarchivo en su ../app/schemas/carpeta. Y se parece a esto:

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "53db508c5248423325bd5393a1c88c03",
    "entities": [
      {
        "tableName": "sms_table",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT, `date` INTEGER, `client_id` INTEGER)",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER"
          },
          {
            "fieldPath": "message",
            "columnName": "message",
            "affinity": "TEXT"
          },
          {
            "fieldPath": "date",
            "columnName": "date",
            "affinity": "INTEGER"
          },
          {
            "fieldPath": "clientId",
            "columnName": "client_id",
            "affinity": "INTEGER"
          }
        ],
        "primaryKey": {
          "columnNames": [
            "id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"53db508c5248423325bd5393a1c88c03\")"
    ]
  }
}

Si mi comprensión es correcta, obtendrá un archivo con cada actualización de la versión de la base de datos, para que pueda seguir fácilmente el historial de su base de datos.

DoruChidean
fuente
8
¿Qué significa realmente "No enviar con su aplicación"? ¿Se incluirá en APK?
Jongz Puangput
2
Si sigue "No enviar con su aplicación", ¿debo eliminar los archivos JSON antes de generar APK?
illusionJJ
8
"No enviar con su aplicación" significa "No establezca schemaLocation como 'app / res / raw'. Establezca schemaLocation en un directorio no incluido en el APK".
galcyurio
3
@galcyurio $ projectDir / schemas es un directorio fuera del APK, ¿verdad? He explorado el APK generado y no lo veo allí. Aunque veo / res (que explica app / src / main / res) por ejemplo.
xarlymg89
1
@glucaio Exploré el APK (y el paquete de aplicaciones también) y no lo encontré. Entonces creo que estamos a salvo.
xarlymg89
390

En el build.gradlearchivo para su módulo de aplicación, agregue esto a la defaultConfigsección (debajo de la androidsección). Esto escribirá el esquema en una schemassubcarpeta de la carpeta de su proyecto.

javaCompileOptions {
    annotationProcessorOptions {
        arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
    }
}

Me gusta esto:

// ...

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    // ... (buildTypes, compileOptions, etc)

}

// ...
mikejonesguy
fuente
35
Si alguien se pregunta, este enfoque exacto también funciona para Kotlin cuando usa kapt
DanielDiSu
1
¿Deberíamos ignorar el archivo json generado en el app/schemasdirectorio por esta operación? Y escuché que deberíamos poner el esquema en un directorio que no está incluido en el apk. ¿Cómo podemos hacer eso?
ravi
2
@ravi el archivo de esquema generado (s) se debe almacenar en el control de versiones, ya que es utilizado por habitación para detectar los cambios y ayudar a asegurar la base de datos si cambia de actualizar la versión de la base de datos y crear un plan de migración
appmattus
1
¿Esta configuración afecta a la versión de lanzamiento? Quiero decir, cuando exporto el proyecto a una aplicación de lanzamiento.
Anargu
Si esta solución resulta en ERROR: No se pudo encontrar la anotación del métodoProcessorOptions () para los argumentos , consulte la respuesta de Luna, a continuación: stackoverflow.com/a/54366985/1617737
ban-geoengineering
185

Kotlin? Aquí vamos:

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }
    }

    buildTypes {
        // ... (buildTypes, compileOptions, etc)
    }
}

//...

No te olvides del complemento:

apply plugin: 'kotlin-kapt'

Para obtener más información sobre el procesador de anotación kotlin, visite: Kotlin docs

Ivanov Maksim
fuente
Como la respuesta: D
theapache64
12

Las respuestas anteriores son correctas. Esta versión es fácil de seguir:

Debido a que "el directorio de exportación de esquema no se proporciona al procesador de anotaciones", debemos proporcionar el directorio para la exportación de esquema:

Paso [1] En tu archivo que extiende la base de datos de Room, cambia la línea a:

`@Database(entities = ???.class,version = 1, exportSchema = true)`

O

`@Database(entities = ???.class,version = 1)` 

(porque el valor predeterminado siempre es verdadero)

Paso [2] En su archivo build.gradle (proyecto: ????), dentro de la configuración predeterminada {} (que está dentro de la sección grande de Android {} ), agregue la sección javaCompileOptions {} , será así:

         android{
                defaultConfig{
                      //javaComplieOptions SECTION
                      javaCompileOptions {
                            annotationProcessorOptions {
                                     arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
                            }
                       }
                      //Other SECTION
                      ...
                }
         }

$ projectDir : es un nombre de variable, no puede cambiarlo. obtendrá su propio directorio de proyectos

esquemas : es una cadena, puede cambiarla a la que desee. Por ejemplo: "$projectDir/MyOwnSchemas".toString()

LunaRivolxoxo
fuente
en el paso [2], ¿estás seguro de que es el build.gradle(project:????)y no build.gradle(app:????)?
As
9

La respuesta de @mikejonesguy es perfecta, en caso de que planee probar las migraciones de salas (recomendado), agregue la ubicación del esquema a los conjuntos de origen.

En su archivo build.gradle, especifica una carpeta para colocar estos archivos JSON de esquema generados. A medida que actualice su esquema, terminará con varios archivos JSON, uno para cada versión. Asegúrese de confirmar cada archivo generado al control de origen. La próxima vez que aumente su número de versión nuevamente, Room podrá usar el archivo JSON para las pruebas.

  • Florina Muntenescu ( fuente )

build.gradle

android {

    // [...]

    defaultConfig {

        // [...]

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    // add the schema location to the source sets
    // used by Room, to test migrations
    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }

    // [...]
}
chebaby
fuente
3

Uso los .ktsarchivos de Gradle (Kotlin Gradle DSL) y el kotlin-kaptcomplemento, pero sigo recibiendo un error de compilación de script cuando uso la respuesta de Ivanov Maksim.

Unresolved reference: kapt

Para mí esto fue lo único que funcionó:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = mapOf("room.schemaLocation" to "$projectDir/schemas")
            }
        }
    }
}
jsa
fuente
Nada funciona para mí tampoco. Estoy usando Kotlin.
nyxee
0

Probablemente no agregaste la clase de tu habitación a RoomDatabasela clase infantil@Database(entities = {your_classes})

Max Zonov
fuente