Aí vai mais uma dica simples, porém apesar de parecer simples estive com o mesmo problema e quando procurei pela solução não encontrei. Percebi que bastante gente também tem essa dúvida, pois encontrei várias perguntas similares no stackoverflow porém todas sem resultados de sucesso.
Então vamos lá, o cenário é o seguinte:
- Você utiliza um database interno no seu App, utilizando o famoso SQLite.
- Você precisa atualizar a versão desse DB para incluir mais registros, ou seja, aumentar o conteúdo do seu App. Porém, você tem uma lista de Favoritos por exemplo, que é alimentada de acordo com o uso de cada usuário.
Problema: ao alterar a versão do DB, a sua classe que estende SQLiteOpenHelper, vai chamar o método onUpgrade para atualizar a versão do DB que já está instalado pela versão anterior do App, e Bye Bye os itens que o usuário marcou como favorito =(
Como disse anteriormente, procurei por várias soluções e não encontrei, fiz várias implementações porém nenhuma fazia o que eu queria que fizesse.
Então a solução que encontrei foi a seguinte:
Na minha MainActivity, ou seja, a primeira tela que inicia com o App, eu criei dois métodos:
pegaVersaoDb(); //busca o valor da versão do DB que está atualmente em funcionamento.
e
atualizaVersaoDb(); //atualiza o DB atual pelo DB da nova versão.
Também utilizei a variável DATABASE_VERSION que geralmente é utilizada no método onUpgrade e é declarada na classe que estende SQLiteOpenHelper.
Ok, tudo pronto para atualizarmos o DB, mas antes queremos salvar os favoritos para que quando acabe de atualizar a versão do App, os favoritos continuem do jeito que estavam.
Então para um melhor entendimento do que foi feito, e para auxiliar à quem procura uma solução, vou colar os códigos e explicar:
// pegaVersaoDb(); busca o valor da versão do DB que está atualmente em funcionamento.
public void pegaVersaoDb(){
Cursor cursor = databaseFav.query(TABLE_VERSION, new String[] {KEY_VERSAO},null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
versao_atual = cursor.getInt(0);
} while (cursor.moveToNext());
}
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
// pegaMusicasFavoritas(); retorna um Cursor com todos os itens marcados como favoritos no DB.
public static Cursor pegaMusicasFavoritas() {
Cursor favCursor = databaseFav.query(true, TABLE_NAME, new String[]
{KEY_ID_ITEM, KEY_NOME, KEY_ITEM_ID, KEY_VALOR }, KEY_FAVORITO + "=?",
new String[] { VALOR_FAVORITO }, null, null, null, null);
if (favCursor != null) {
favCursor.moveToFirst();
}
return favCursor;
}
// atualizaVersaoDb(); atualiza o DB atual pelo DB da nova versão.
public void atualizaVersaoDb(SQLiteDatabase db, int versaoAtual, int novaVersao){
try {
if(versaoAtual == novaVersao){
Log.d("atualizarVersaoDb", "Nao e necessario atualizar, versao mais nova ja instalada.");
}
if(versaoAtual < novaVersao){
Log.d("CursorSalvaFav", "O método foi acionado e os favoritos será carregado...");
Cursor cursorSalvaFav = pegaMusicasFavoritas();
Log.d("CursorSalvaFav", "Favoritos carregados no cursor");
Log.d("CursorSalvaFav", "Número de favoritos: " + cursorSalvaFav.getCount());
dbOpenHelper.copyDataBase();
if(cursorSalvaFav.getCount() == 0){
Log.d("CursorSalvaFav", "Não há nenhum item marcado como favorito!");
} else {
do {
Log.d("CursorSalvaFav", "Tem favoritos!");
String nome_item = cursorSalvaFav.getString(0);
String id_item = cursorSalvaFav.getString(2);
ContentValues values = new ContentValues();
values.put(KEY_FAVORITO, 1);
Log.d("CursorSalvaFav", "inseriu o valor 1 no fav");
databaseFav.update(TABLE_NAME, values, KEY_ID_ITEM + "=?" + " AND " + KEY_ITEM_ID + "=?", new String[] { nome_item, id_item });
Log.d("CursorSalvaFav", "Realizou update!");
} while (cursorSalvaFav.moveToNext());
}
}
} catch (IOException mIOException) {
Log.e("OnUpgrade", mIOException.toString());
}
}
Agora vamos entender tudo o que foi feito na ordem como é executada as coisas dentro do método onCreate:
//iniciei meu DB na variável dbOpenHelper
dbOpenHelper = new ExternalDbOpenHelper(getActivity(),DB_NAME);
//armazenei a versão do NOVO DB na variável nova_versao, o valor dessa versão é o mesmo valor que está no DB que você atualizou para lançar a nova versão (exemplo: se o DB antigo era versão 1, o valor da nova versão poderá ser 2)
nova_versao = dbOpenHelper.DATABASE_VERSION;
//armazeno o meu DB na variável databaseFav
databaseFav = dbOpenHelper.openDataBase();
//chamo o método que me traz a versão do meu DB que atualmente está sendo utilizado no App
//Aqui está um ponto importante, pois o valor que ele vai pegar aqui ainda não é o valor do DB novo, por exemplo versão 2. O valor ainda é a versão 1, pois o database novo não foi colocado no lugar do antigo, ele apenas está dentro do pacote novo do App (o .apk novo).
pegaVersaoDb();
//Aqui está outro ponto importante, eu chamo o método que decide se será necessário atualizar ou não o DB e se vai ser necessário ou não salvar os favoritos, decisão tomada com base nos valores que estou passando para ele
atualizaVersaoDb(databaseFav, versao_atual, nova_versao);
Como podemos ver no código desse método, ele verifica se a versão do meu DB foi alterada ou não, porque não é em toda versão do App que você vai precisar atualizar seu DB, as vezes você vai lançar uma versão apenas para corrigir um bug ou alguma coisa que não está relacionada ao DB e a versão do DB não será alterada.
Se esse for o caso, o método vai verificar que a versão do DB não foi alterada e apenas vai imprimir no log a seguinte mensagem "Nao e necessario atualizar, versao mais nova ja instalada."
Porém se o DB foi atualizado, ou seja, você modificou os registros dele, alterou a versão dele e alterou a versão da sua variável DATABASE_VERSION, ele vai ver que o código novo que está no novo .apk, está dizendo que a versão do DB é maior do que a versão atual, então o DB deve ser substituído por um novo.... Mas antes, devemos salvar os favoritos do usuário para que eles não sejam apagados.
Então como podemos ver no código, antes de chamar o método copyDataBase()(método responsável por fazer esse processo de substituir o DB por outro), eu chamo o método que salva os favoritos já retornando todos os valores em um cursor Cursor cursorSalvaFav = pegaMusicasFavoritas();
Após isso eu posso já copiar a minha base de dados nova no lugar da antiga e então verificar se tinha algum item marcado como favorito, no caso positivo, eu faço um update no DB novo, mudando o valor default do favorito (zero) para 1, sendo assim marcando os itens como favorito novamente, conforme esse trecho:
do {
Log.d("CursorSalvaFav", "Tem favoritos!");
String nome_item = cursorSalvaFav.getString(0);
String id_item = cursorSalvaFav.getString(2);
ContentValues values = new ContentValues();
values.put(KEY_FAVORITO, 1);
Log.d("CursorSalvaFav", "inseriu o valor 1 no fav");
databaseFav.update(TABLE_NAME, values, KEY_ID_ITEM + "=?" + " AND " + KEY_ITEM_ID + "=?", new String[] { nome_item, id_item });
Log.d("CursorSalvaFav", "Realizou update!");
} while (cursorSalvaFav.moveToNext());
}
}
} catch (IOException mIOException) {
Log.e("OnUpgrade", mIOException.toString());
}
//Pronto, agora sim posso prosseguir normalmente com a execução do código, pois minha base foi atualizada e os favoritos não foram perdidos, então carrego a lista de favoritos para alimentar minha listView na tela.
cursorFav = pegaMusicasFavoritas();
Agora você me pergunta, porque você não chamou o método pegaMusicasFavoritas(), dentro do método onUpgrade da classe que controla o seu DB? Dessa forma ele iria fazer a mesma coisa, porém com menos código.
Aí eu te respondo, ok por boa prática e como já existe algo pronto que faça essa comparação de versões dos DB's pra gente, o certo realmente seria utilizar o onUpgrade, porém de maneira alguma ele funcionou da forma como eu queria, além do que como ele é algo "pronto", eu não sabia o que ele estava fazendo internamente. Da forma como eu fiz "manualmente" fica fácil de saber o que está acontecendo durante todo o processo, e me deixou com mais confiança de que ele seria executado sempre que necessário.
Gambiarra? Não, isso é solução, para mim essa solução serviu e ainda continua servindo corretamente.
E para você? Foi útil? Deixe sua opinião, sugestão ou dúvida.
Obrigado e até a próxima!
Abraço!


















