Empacotar um arquivo Realm - SDK Java
Nesta página
Observação
Agrupar domínios sincronizados
A versão 10.9.0 do SDK introduziu a capacidade de agrupar domínios sincronizados. Antes da versão 10.9.0, você só podia agrupar domínios locais.
O Realm suporta o agrupamento de arquivos realm. Ao agrupar um arquivo de domínio, você inclui um banco de dados e todos os seus dados no download do aplicativo.
Isso permite que os usuários iniciem aplicativos pela primeira vez com um conjunto de dados iniciais. Para domínios sincronizados, o agrupamento pode evitar um download inicial demorado na primeira vez que um usuário abre seu aplicação. Em vez disso, os usuários devem baixar apenas as alterações sincronizadas que ocorreram desde que você gerou o arquivo agrupado.
Importante
Agrupar domínios sincronizados
Se o seu aplicação de backend usar Flexible Sync, os usuários poderão enfrentar um reinício do cliente na primeira vez que abrirem o arquivo de Realm agrupado. Isso pode ocorrer quando o tempo máximo offline do cliente está habilitado (o tempo máximo offline do cliente está habilitado por padrão). Se o arquivo de Realm agrupado tiver sido gerado mais do que o número de dias especificado pela configuração de tempo máximo offline do cliente antes de o usuário sincronizar pela primeira vez, o usuário experimenta uma reinício do cliente.
Os aplicativos que executam uma redefinição do cliente baixam o estado completo do domínio do backend do aplicativo. Isso nega as vantagens de agrupar um arquivo de domínio. Para evitar o reinício do cliente e preservar as vantagens do agrupamento de arquivos realm:
Evite usar o tempo offline máximo do cliente em aplicativos que agrupam um domínio sincronizado.
Se o seu aplicativo usar o tempo máximo offline do cliente, certifique-se de que o download do aplicativo sempre inclua um arquivo de domínio sincronizado recentemente. Gere um novo arquivo a cada versão do aplicativo e garanta que nenhuma versão permaneça atual por mais do que o número máximo de dias de tempo offline do cliente .
Visão geral
Para criar e agrupar um arquivo de domínio com seu aplicativo:
Crie um arquivo de domínio que contenha os dados que você deseja agrupar.
Agrupe o arquivo realm na pasta
/<app name>/src/main/assets
do seu aplicativo de produção.Em seu aplicativo de produção, abra o domínio a partir do arquivo de ativos agrupados. Para domínios sincronizados, você deve fornecer a chave de partição.
Observação
Somente sincronização do mesmo tipo
Esse método oferece suporte apenas à cópia de uma configuração de Partition-Based Sync para outro usuário de Partition-Based Sync ou uma configuração de Flexible Sync para outro usuário de Flexible Sync. Você não pode usar esse método para converter entre um Partition-Based Sync realm e um Flexible Sync realm ou vice-versa.
Criar um arquivo Realm para agrupamento
Construa um aplicativo de domínio temporário que compartilhe o modelo de dados do seu aplicativo.
Abra um domínio e adicione os dados que deseja agrupar. Se estiver usando um domínio sincronizado, dê tempo para que o domínio sincronize totalmente.
Use o método writeCopyTo() para copiar o domínio para um novo arquivo:
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(appID); Credentials anonymousCredentials = Credentials.anonymous(); app.loginAsync(anonymousCredentials, it -> { if (it.isSuccess()) { Log.v("EXAMPLE", "Successfully authenticated anonymously."); String PARTITION = "PARTITION_YOU_WANT_TO_BUNDLE"; // you can only create realm copies on a background thread with a looper. // HandlerThread provides a Looper-equipped thread. HandlerThread handlerThread = new HandlerThread("CopyARealmHandler"); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()); handler.post(new Thread(new Runnable() { public void run() { SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION) // wait for the realm to download all data from the backend before opening .waitForInitialRemoteData() .build(); Realm realm = Realm.getInstance(config); Log.v("EXAMPLE", "Successfully opened a realm."); // write a copy of the realm you can manually copy to your production application assets File outputDir = activity.getApplicationContext().getCacheDir(); File outputFile = new File(outputDir.getPath() + "/" + PARTITION + "_bundled.realm"); // ensure all local changes have synced to the backend try { app.getSync().getSession(config).uploadAllLocalChanges(10000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); } // cannot write to file if it already exists. Delete the file if already there outputFile.delete(); realm.writeCopyTo(outputFile); // search for this log line to find the location of the realm copy Log.i("EXAMPLE", "Wrote copy of realm to " + outputFile.getAbsolutePath()); // always close a realm when you're done using it realm.close(); }})); } else { Log.e("EXAMPLE", "Failed to authenticate: " + it.getError().toString()); } }); val appID: String = YOUR_APP_ID // replace this with your App ID val app = App(appID) val anonymousCredentials = Credentials.anonymous() app.loginAsync(anonymousCredentials) { it: App.Result<User?> -> if (it.isSuccess) { Log.v("EXAMPLE", "Successfully authenticated anonymously.") val PARTITION = "PARTITION_YOU_WANT_TO_BUNDLE" // you can only create realm copies on a background thread with a looper. // HandlerThread provides a Looper-equipped thread. val handlerThread = HandlerThread("CopyARealmHandler") handlerThread.start() val handler = Handler(handlerThread.looper) handler.post(Thread { val config = SyncConfiguration.Builder(app.currentUser(), PARTITION) // wait for the realm to download all data from the backend before opening .waitForInitialRemoteData() .build() val realm : Realm = Realm.getInstance(config); Log.v("EXAMPLE", "Successfully opened a realm.") // write a copy of the realm you can manually copy to your production application assets val outputDir = activity!!.applicationContext.cacheDir val outputFile = File(outputDir.path + "/" + PARTITION + "_bundled.realm") // ensure all local changes have synced to the backend try { app.sync.getSession(config) .uploadAllLocalChanges(10000, TimeUnit.MILLISECONDS) } catch (e: InterruptedException) { e.printStackTrace() } // cannot write to file if it already exists. Delete the file if already there outputFile.delete() realm.writeCopyTo(outputFile) // search for this log line to find the location of the realm copy Log.i("EXAMPLE", "Wrote copy of realm to " + outputFile.absolutePath) // always close a realm when you're done using it realm.close() }) } else { Log.e("EXAMPLE", "Failed to authenticate: ${it.error}") } } writeCopyTo()
compacta automaticamente seu domínio no menor tamanho possível antes de copiar.Dica
Diferenças entre domínios sincronizados e domínios somente locais
O exemplo acima utiliza um
SyncConfiguration
para configurar um realm sincronizado. Para criar uma cópia de um realm local, configure seu realm comRealmConfiguration
.
Agrupe um arquivo Realm em seu aplicativo de produção
Agora que você tem uma cópia do domínio que contém os dados iniciais, agrupe-o com seu aplicativo de produção.
Pesquisar os registros da aplicação para encontrar o local da cópia do Arquivo de Realm que você acabou de criar.
Usando o widget "Device File Explorer" no canto inferior direito da janela do Android Studio, navegue até o arquivo.
Clique com o botão direito do mouse no arquivo e selecione "Salvar como". Navegue até a pasta
/<app name>/src/main/assets
do seu aplicativo de produção. Salve uma cópia do Arquivo de Realm lá.
Dica
Pastas de ativos
Se o seu aplicativo ainda não contiver uma pasta de ativos, você poderá criar uma clicando com o botão direito do mouse na pasta do aplicativo de nível superior (<app name>
) no Android Studio e selecionando New > Folder > Assets Folder no menu.
Abrir um Realm a partir de um arquivo de Realm agrupado
Agora que você tem uma cópia do Realm incluída em seu aplicação de produção, precisa adicionar código para usá-lo. Use o método ativoFile() ao configurar seu Realm para abrir o Realm a partir do arquivo agrupado:
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(appID); Credentials anonymousCredentials = Credentials.anonymous(); app.loginAsync(anonymousCredentials, it -> { if (it.isSuccess()) { Log.v("EXAMPLE", "Successfully authenticated anonymously."); // asset file name should correspond to the name of the bundled file SyncConfiguration config = new SyncConfiguration.Builder( app.currentUser(), "PARTITION_YOU_WANT_TO_BUNDLE") .assetFile("example_bundled.realm") .build(); Realm realm = Realm.getInstance(config); Log.v("EXAMPLE", "Successfully opened bundled realm."); // read and write to the bundled realm as normal realm.executeTransactionAsync(transactionRealm -> { Frog frog = new Frog(new ObjectId(), "Asimov", 4, "red eyed tree frog", "Spike"); transactionRealm.insert(frog); expectation.fulfill(); }); } else { Log.e("EXAMPLE", "Failed to authenticate: " + it.getError().toString()); } });
val appID: String = YOUR_APP_ID // replace this with your App ID val app = App(appID) val anonymousCredentials = Credentials.anonymous() app.loginAsync(anonymousCredentials) { it: App.Result<User?> -> if (it.isSuccess) { Log.v("EXAMPLE", "Successfully authenticated anonymously.") // asset file name should correspond to the name of the bundled file val config = SyncConfiguration.Builder( app.currentUser(), "PARTITION_YOU_WANT_TO_BUNDLE") .assetFile("example_bundled.realm") .build() val realm: Realm = Realm.getInstance(config) Log.v("EXAMPLE", "Successfully opened bundled realm.") // read and write to the bundled realm as normal realm.executeTransactionAsync { transactionRealm: Realm -> val frog = Frog( ObjectId(), "Asimov", 4, "red eyed tree frog", "Spike" ) transactionRealm.insert(frog) expectation.fulfill() } } else { Log.e("EXAMPLE", "Failed to authenticate: ${it.error}") } }
Dica
Diferenças entre domínios sincronizados e domínios somente locais
O exemplo acima utiliza um SyncConfiguration
para configurar um realm sincronizado. Para criar uma cópia de um realm local, configure seu realm com RealmConfiguration
.