O diretório de exportação Room - Schema não é fornecido para o processador de anotação, portanto, não podemos exportar o esquema

349

Estou usando a Sala de componentes do banco de dados do Android

Eu configurei tudo, mas quando compilo, o Android Studio me dá este aviso:

O diretório de exportação do esquema não é fornecido para o processador de anotação, portanto, não podemos exportar o esquema. Você pode fornecer o room.schemaLocationargumento do processador de anotação OU definir exportSchema como false.

Pelo que entendi, é o local onde o arquivo DB estará localizado

Como isso pode afetar meu aplicativo? Qual é a melhor prática aqui? Devo usar o local padrão ( falsevalor)?

Misha Akopov
fonte

Respostas:

395

Conforme os documentos :

Você pode definir o argumento do processador de anotação (room.schemaLocation) para solicitar ao Room para exportar o esquema para uma pasta. Mesmo que não seja obrigatório, é uma boa prática ter o histórico de versões na sua base de código e você deve confirmar esse arquivo no seu sistema de controle de versões (mas não o envie com o seu aplicativo!).

Portanto, se você não precisar verificar o esquema e quiser se livrar do aviso, basta adicioná-lo exportSchema = falseao RoomDatabaseseguinte.

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

Se você seguir a resposta @mikejonesguy abaixo, seguirá as boas práticas mencionadas na documentação :). Basicamente, você receberá um .jsonarquivo em sua ../app/schemas/pasta. E parece algo como isto:

{
  "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\")"
    ]
  }
}

Se meu entendimento estiver correto, você receberá esse arquivo a cada atualização de versão do banco de dados, para poder acompanhar facilmente o histórico do seu banco de dados.

DoruChidean
fonte
7
O que realmente significa "Não enviar com seu aplicativo"? Será incluído no APK?
Jongz Puangput
2
Se seguir "Não enviar com seu aplicativo", devo remover arquivos JSON antes de gerar APK?
illusionJJ
7
"Não enviar com o seu aplicativo" significa "Não definir o schemaLocation como 'app / res / raw'. Defina o schemaLocation como um diretório não incluído no APK."
galcyurio
3
@galcyurio $ projectDir / schemas é um diretório fora do APK, certo? Eu explorei o APK gerado e não o vejo por lá. Embora eu veja / res (que representa app / src / main / res), por exemplo.
xarlymg89
11
@glucaio Eu explorei o APK (e o pacote de aplicativos também) e não o encontrei. Então eu acredito que estamos seguros.
xarlymg89
388

No build.gradlearquivo do seu módulo de aplicativo, adicione-o à defaultConfigseção (sob a androidseção). Isso gravará o esquema em uma schemassubpasta da pasta do projeto.

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

Como isso:

// ...

android {

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

    defaultConfig {

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

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

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

}

// ...
mikejonesguy
fonte
34
Se alguém está se perguntando, esta abordagem exata também funciona para Kotlin ao usar Kapt
DanielDiSu
11
Devemos gitignore o arquivo json gerado no app/schemasdiretório por esta operação. E ouvi dizer que devemos colocar o esquema em um diretório que não esteja incluído no arquivo apk. Como podemos fazer isso?
ravi
2
@ravi, os arquivos de esquema gerados devem ser armazenados no controle de versão, pois isso é usado pelo Room para detectar alterações e ajudar a garantir que, se o banco de dados alterar, você atualize a versão do banco de dados e crie um plano de migração
appmattus
11
Essa configuração afeta a versão de lançamento? Quero dizer, quando exporto o projeto para um aplicativo de lançamento.
Anargu 12/09/18
Se esta solução resulta em Erro: Não foi possível encontrar annotationProcessorOptions método () para argumentos , veja a resposta de Luna, abaixo: stackoverflow.com/a/54366985/1617737
ban-geoengenharia
184

Kotlin? Aqui vamos nós:

android {

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

    defaultConfig {

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

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

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

//...

Não se esqueça do plugin:

apply plugin: 'kotlin-kapt'

Para mais informações sobre o processador de anotações kotlin, visite: Kotlin docs

Ivanov Maksim
fonte
Do jeito que você respondeu: D
theapache64
12

As respostas acima estão corretas. Esta versão é fácil de seguir:

Como "O diretório de exportação do esquema não é fornecido para o processador de anotação", precisamos fornecer o diretório para a exportação do esquema:

Etapa [1] No seu arquivo que estende o RoomDatabase, altere a linha para:

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

Ou

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

(porque o valor padrão é sempre verdadeiro)

Etapa [2] No seu arquivo build.gradle (projeto: ????), dentro da seção defaultConfig {} (que fica dentro da seção grande do android {} ), adicione a seção javaCompileOptions {} , será como:

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

$ projectDir : é um nome de variável, você não pode alterá-lo. ele receberá seu próprio diretório de projeto

schemas : é uma string, você pode alterá-la para qualquer que quiser. Por exemplo: "$projectDir/MyOwnSchemas".toString()

LunaRivolxoxo
fonte
no passo [2], você tem certeza de que é build.gradle(project:????)e não build.gradle(app:????)?
Ace
9

A resposta @mikejonesguy é perfeita, caso você planeje testar as migrações da sala (recomendado), adicione o local do esquema aos conjuntos de fontes.

No arquivo build.gradle, você especifica uma pasta para colocar esses arquivos JSON de esquema gerados. Ao atualizar seu esquema, você terminará com vários arquivos JSON, um para cada versão. Certifique-se de confirmar todos os arquivos gerados no controle de origem. Na próxima vez que você aumentar seu número de versão, o Room poderá usar o arquivo JSON para teste.

  • Florina Muntenescu ( fonte )

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
fonte
3

Uso .ktsarquivos Gradle (Kotlin Gradle DSL) e o kotlin-kaptplug - in, mas ainda recebo um erro de compilação de script quando uso a resposta de Ivanov Maksim.

Unresolved reference: kapt

Para mim, foi a única coisa que funcionou:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = mapOf("room.schemaLocation" to "$projectDir/schemas")
            }
        }
    }
}
jsa
fonte
Nada está funcionando para mim também. Estou usando o Kotlin.
nyxee 6/04
0

Provavelmente você não adicionou sua classe de quarto à classe infantil RoomDatabaseinfantil em@Database(entities = {your_classes})

Max Zonov
fonte