Implementei um BackupAgentHelper
usando o fornecido FileBackupHelper
para fazer backup e restaurar o banco de dados nativo que tenho. Este é o banco de dados que você normalmente usa junto com o ContentProviders
qual reside /data/data/yourpackage/databases/
.
Alguém poderia pensar que este é um caso comum. No entanto, os documentos não são claros sobre o que fazer: http://developer.android.com/guide/topics/data/backup.html . Não há nenhum BackupHelper
específico para esses bancos de dados típicos. Portanto, usei oFileBackupHelper
, apontei para meu arquivo .db em " /databases/
", introduzi bloqueios em qualquer operação db (como db.insert
) em meu ContentProviders
e até tentei criar o /databases/
diretório " " antes onRestore()
porque ele não existe após a instalação.
Implementei uma solução semelhante para o SharedPreferences
sucesso em um aplicativo diferente no passado. No entanto, quando testo minha nova implementação no emulador-2.2, vejo um backup sendo executado a LocalTransport
partir dos logs, bem como uma restauração sendo realizada (e onRestore()
chamada). No entanto, o próprio arquivo db nunca é criado.
Observe que tudo isso ocorre após a instalação e antes da primeira inicialização do aplicativo, após a execução da restauração. Além disso, minha estratégia de teste foi baseada em http://developer.android.com/guide/topics/data/backup.html#Testing .
Observe também que não estou falando sobre algum banco de dados sqlite que eu mesmo gerencio, nem sobre backup em SDcard, servidor próprio ou em outro lugar.
Eu vi uma menção nos documentos sobre bancos de dados que aconselham o uso de um personalizado, BackupAgent
mas não parece relacionado:
No entanto, você pode desejar estender o BackupAgent diretamente se precisar: * Fazer backup dos dados em um banco de dados. Se você tiver um banco de dados SQLite que deseja restaurar quando o usuário reinstalar seu aplicativo, será necessário construir um BackupAgent personalizado que leia os dados apropriados durante uma operação de backup e, em seguida, crie sua tabela e insira os dados durante uma operação de restauração.
Alguma clareza, por favor.
Se eu realmente preciso fazer isso sozinho até o nível SQL, estou preocupado com os seguintes tópicos:
Abra bancos de dados e transações. Não tenho ideia de como fechá-los a partir de uma classe única fora do fluxo de trabalho do meu aplicativo.
Como notificar o usuário de que um backup está em andamento e o banco de dados está bloqueado. Pode demorar muito, então posso precisar mostrar uma barra de progresso.
Como fazer o mesmo na restauração. Pelo que entendi, a restauração pode acontecer apenas quando o usuário já começou a usar o aplicativo (e inserir dados no banco de dados). Portanto, você não pode presumir apenas restaurar os dados do backup no local (excluindo os dados vazios ou antigos). Você terá que juntá-lo de alguma forma, o que para qualquer banco de dados não trivial é impossível devido ao id.
Como atualizar o aplicativo após a restauração sem deixar o usuário preso em algum ponto - agora - inacessível.
Posso ter certeza de que o banco de dados já foi atualizado no backup ou restauração? Caso contrário, o esquema esperado pode não corresponder.
Respostas:
Uma abordagem mais limpa seria criar um personalizado
BackupHelper
:e depois adicione-o a
BackupAgentHelper
:fonte
Depois de rever minha pergunta, consegui fazê-lo funcionar depois de ver como o ConnectBot o faz . Obrigado Kenny e Jeffrey!
Na verdade, é tão fácil quanto adicionar:
para o seu
BackupAgentHelper
.O que estava faltando era o fato de que você teria que usar um caminho relativo com "
../databases/
".Ainda assim, esta não é uma solução perfeita. Os documentos para
FileBackupHelper
menção, por exemplo: "FileBackupHelper
devem ser usados apenas com pequenos arquivos de configuração, não grandes arquivos binários. ", Sendo o último o caso com bancos de dados SQLite.Gostaria de obter mais sugestões, percepções sobre o que se espera de nós (qual é a solução adequada) e conselhos sobre como isso pode falhar.
fonte
db.open()
por meiodb.close()
ou apenas deinsert
instruções ou o quê.Aqui está uma maneira mais limpa de fazer backup de bancos de dados como arquivos. Nenhum caminho codificado.
Nota: ele substitui getFilesDir para que FileBackupHelper funcione no diretório de bancos de dados, não no diretório de arquivos.
Outra dica: você também pode usar databaseList para obter todos os seus nomes de banco de dados e feed desta lista (sem o caminho pai) para FileBackupHelper. Então, todos os bancos de dados do aplicativo seriam salvos no backup.
fonte
Usar
FileBackupHelper
para fazer backup / restaurar sqlite db levanta algumas questões sérias:1. O que acontecerá se o aplicativo usar o cursor recuperado
ContentProvider.query()
e o agente de backup tentar substituir o arquivo inteiro?2. O link é um bom exemplo de teste perfeito (baixa entrofia;). Você desinstala o aplicativo, instala-o novamente e o backup é restaurado. No entanto, a vida pode ser brutal. Dê uma olhada no link . Vamos imaginar o cenário em que um usuário compra um novo dispositivo. Como não tem seu próprio conjunto, o agente de backup usa o conjunto de outro dispositivo. O aplicativo é instalado e seu backupHelper recupera o arquivo antigo com esquema de versão db inferior ao atual.
SQLiteOpenHelper
chamadasonDowngrade
com a implementação padrão:Não importa o que o usuário faça, ele não pode usar seu aplicativo no novo dispositivo.
Eu sugiro usar
ContentResolver
para obter dados -> serializar (sem_id
s) para backup e desserializar -> inserir dados para restauração.Nota: obter / inserir dados é feito através do ContentResolver, evitando assim problemas de moeda. A serialização é feita em seu backupAgent. Se você fizer seu próprio mapeamento de cursor <-> objeto, serializar um item pode ser tão simples quanto implementar
Serializable
com otransient
campo _id na classe que representa sua entidade.Eu também usar a granel inserção ou seja
ContentProviderOperation
exemplo eCursorLoader.setUpdateThrottle
para que o aplicativo não está preso com o reinício loader sobre a mudança de dados durante o backup processo de restauração.Se você estiver em uma situação de downgrade, pode optar por abortar a restauração dos dados ou restaurar e atualizar o ContentResolver com campos relevantes para a versão rebaixada.
Eu concordo que o assunto não é fácil, não é bem explicado nos documentos e algumas questões ainda permanecem como tamanho de dados em massa etc.
Espero que isto ajude.
fonte
A partir do Android M, agora existe uma API de backup / restauração de dados completos disponível para aplicativos. Essa nova API inclui uma especificação baseada em XML no manifesto do aplicativo que permite ao desenvolvedor descrever quais arquivos fazer backup de uma forma semântica direta: 'faça backup do banco de dados chamado "mydata.db"'. Esta nova API é muito mais fácil para os desenvolvedores usarem - você não precisa acompanhar as diferenças ou solicitar uma passagem de backup explicitamente, e a descrição XML de quais arquivos fazer backup significa que muitas vezes você não precisa escrever nenhum código em absoluto.
(Você pode se envolver até mesmo em uma operação de backup / restauração de dados completos para obter um retorno de chamada quando a restauração acontecer, por exemplo. É flexível dessa forma.)
Consulte a seção Configuração do backup automático para aplicativos em developer.android.com para obter uma descrição de como usar a nova API.
fonte
Uma opção será construí-lo na lógica do aplicativo acima do banco de dados. Na verdade, ele grita por tal nível, eu acho. Não tenho certeza se você já está fazendo isso, mas a maioria das pessoas (apesar da abordagem do cursor do gerenciador de conteúdo do Android) irá introduzir algum mapeamento ORM - seja personalizado ou uma abordagem orm-lite. E o que eu prefiro fazer neste caso é:
Portanto, neste caso, em vez de fazer no nível do banco de dados, faça no nível do aplicativo.
fonte