Utilizando Banco de Dados em Desenvolvimento Android

On 4 de março de 2014 by Vicente Amorim

Introdução

Este post possui como objetivo explicar e exemplificar a utilização do Banco de Dados em desenvolvimento Android ressaltando a importância de seu uso. Durante este estudo, serão apresentado dois métodos de criação do Banco de Dados, utilizando a ferramenta SQLite Expert Personal, freeware disponível neste endereço, e através da API para SQLite presente no framework Android.

SQLite

Visto o aperfeiçoamento dos smartphones atuais em relação a processamento e armazenamento, as aplicações presentes em tais dispositivos ainda não são aplicações com gigabytes de dados e também com muita concorrência dos processos. Por este motivo, o Android possui suporte ao SQLite durante o seu desenvolvimento. O SQLite não se enquadra na categoria de Sistema de Gerenciamento de Banco de Dados (SGBD), pois, por definição, o SQLite é uma biblioteca, escrita em C, que possui operações de leitura e escrita nos próprios arquivos de banco de dados. Por acessar diretamente os arquivos, o seu custo de memória para a sua implantação é inferior aos SGBDs conhecidos. Sua utilização se destaca principalmente em sistemas embarcados e dispositivos.

Criação do Banco de Dados através do SQLite Expert Personal

Como dito anteriormente, para a criação de um banco de dados em uma aplicação móvel através de uma interface gráfica, existe a ferramenta SQLite Expert Personal, disponível neste endereço. Este tópico abordará o passo-a-passo desde a instalação do software até o seu uso, incluindo a criação do banco de dados.

Tela 1 de Instalação do SQLite Expert Personal

Tela 1 de Instalação do SQLite Expert Personal

Clique em Next para passar para a próxima tela de instalação.

Tela 2 de Instalação do SQLite Expert Personal

Tela 2 de Instalação do SQLite Expert Personal

Após a leitura dos termos de uso, Marque a opção de “I accept the agreeement”, dizendo assim estar ciente dos termos de uso e os aprova. À seguir, clique em “Next” para dar prosseguimento.

Tela 3 de Instalação do SQLite Expert Personal

Tela 3 de Instalação do SQLite Expert Personal

Para a instalação da ferramenta existe um diretório padrão, mas que pode ser alterado nesta tela, após a escolha do diretório, clique em “Next” para ir a próxima tela.

Tela 4 de Instalação do SQLite Expert Personal

Tela 4 de Instalação do SQLite Expert Personal

Tela 5 de Instalação do SQLite Expert Personal

Tela 5 de Instalação do SQLite Expert Personal

Opções adicionais para a instalação, onde a primeira opção, se marcada, cria um atalho do programa na Área de Trabalho do computador. A segunda opção, se marcada, cria um atalho de acesso rápido no computador.

Tela 6 de Instalação do SQLite Expert Personal

Tela 6 de Instalação do SQLite Expert Personal

Após todas as configurações serem definidas, esta tela confirmará todas as informações, e ao clicar em “Install”, uma barra de progresso indicará o término da instalação da ferramenta.

Tela 7 de Instalação do SQLite Expert Personal

Tela 7 de Instalação do SQLite Expert Personal

Esta tela apresentará a finalização da instalação da ferramenta. Para encerrar o processo de instalação, clique em “Finish”.

Após a instalação e inicialização da ferramenta, é hora de colocar em prática o tutorial. Primeiramente, a criação do banco de dados, ao acessar o menu File e clicar no item New Database. Será aberto uma janela com dois campos em branco:

Criação de novo banco de dados

Criação de novo banco de dados

  • Database file: O banco de dados em disco que será importado ao emulador.
  • Database alias: O apelido para uma fácil referência ao banco de dados.

Para este exemplo de uso, preencheremos, respectivamente, com os seguintes dados: c:\temp\livro_android o campo Database File, e livro_android o campo Database Alias.

O diretório, neste caso, c:\temp\, necessariamente, precisa existir para a criação do banco de dados. Ao clicar em “OK”, é aberto uma nova tela e um arquivo, sem extensão, é criado no diretório escolhido, e, futuramente, este arquivo será importado ao emulador.

A tela aberta deve ser semelhante ao que a figura abaixo representa, contendo ao lado esquerdo um acesso por árvore dos bancos de dados criados, uma tela de entrada, onde existem as guias:

  • Database: Onde é possível ver os banco de dados existentes ;
  • SQLOnde é possível entrar com scripts em SQL para a execução, ao apertar F5, ou ao clicar com o botão direito do mouse e selecionar a opção executar;
  • DataOnde é possível ver o conteúdo da tabela selecionada ao lado esquerdo;
  • DesignOnde é possível ver a estrutura da tabela selecionada ao lado esquerdo;
  • DDLOnde é possível ver o código de criação da tabela selecionada ao lado esquerdo;

Existe ainda uma tela de saída, onde são apresentadas as informações das operações realizadas.

Tela do SQLite Expert Personal

Tela do SQLite Expert Personal

Selecione a guia “SQL” e Adicione o seguinte script em SQL, para a construção de uma tabela “carro”, onde seus atributos são:
  • _idrepresenta um código identificador – chave primária; 
  • nomecampo que representa o nome do carro;
  • placacampo que representa a placa do carro;
  • ano: campo que repesenta o ano do carro.

[sourcecode language=”sql”]
create table carro (_id integer primary key autoincrement, nome text not null, placa text not null, ano text not null);
insert into carro (nome, placa, ano) values (‘Fusca A’, ‘ABC-1234’, 1950);
insert into carro (nome, placa, ano) values (‘Brasília B’, ‘DEF-5678’, 1960);
insert into carro (nome, placa, ano) values (‘Chevete C’, ‘GHI-9999’, 1970);
[/sourcecode]

As figuras abaixo representam como cada aba/guia apresenta ao usuário seus respectivos dados.

Guia Database

Guia Database

Guia SQL

Guia SQL

Guia Data

Guia Data

Guia Designs

Guia Designs

Guia DDL

Guia DDL

Importação do banco de dados para o emulador Android

Após toda a criação do banco de dados da aplicação, o próximo passo é a importação do mesmo para o emulador. Para realizar a importação, é necessário criar um projeto Android primeiro, pois o banco de dados é salvo no pacote da aplicação. Neste exemplo, criaremos o projeto LivroAndroid-Cap14-BancoDados e dentro deste projeto, criaremos um pacote chamado br.livro.android.cap14.banco. Crie uma classe chamada CadastroCarros neste novo pacote, resultando na estrutura que é apresentada na figura abaixo.

Árvore do projeto Android

Árvore do projeto Android

Após essa estrutura básica do projeto, pode-se importar o banco de dados para ser utilizado na classe criada CadastroCarros. Para importar o banco de dados, primeiramente, coloque a seguinte linha de código no onCreate da Activity principal:

[sourcecode language=”java”]
SQLiteDatabase db = openOrCreateDatabase("livro_android", Context.MODE_PRIVATE,null);
[/sourcecode]

Onde:

  • O primeiro parâmetro é o nome do banco de dados;
  • O segundo parâmetro é o modo de abertura, podendo variar entre: “Context.MODE_PRIVATE“, permitindo apenas a aplicação atual utilizar o banco de dados; “Context.MODE_READABLE”, permitindo que outras aplicações consigam ler o banco de dados; ou “Context.MODE_WRITEABLE”, permitindo que as outras aplicações consigam escrever no banco de dados em questão;
  • O terceiro parâmetro é um campo opcional do tipo CursorFactory. Quando passado o parâmetro “null”, o cursor padrão é utilizado.

Após a inserção desta linha, compile o código para criar a aplicação no Sistema Operacional. Abra a janela Window > Open Perspective > Other > DDMS > File Explorer e busque pelo caminho: /data/data/nomeDoProjeto/databases e envie o arquivo sem extensão livro_android, criado no tópico anterior, para esta pasta. O envio pode ser feito arrastando o arquivo e soltando na pasta ou através da opção “push a file onto the device”, que possui como ícone, um pequeno celular.

Realização das operações no banco de dados
Este tópico destina-se a explicar e exemplificar as operações básicas do banco de dados criado, subdividindo-se em tópicos para inserção, atualização, remoção e busca de registros.
Inserção de registros
A inserção de registros acontece através do objeto ContentValues que a partir do sistema de chaves e valores, busca realizar a operação de inserção.
[sourcecode language=”java”]
//Inserção dos valores
ContentValues valores = new ContentValues();
valores.put("nome","Carro");
valores.put("placa","AAA-1111");
valores.put("ano",2008);

//Inserção dos dados no banco de dados
//db é do tipo SQLiteDatabase
db.insert("carro", null, valores);
[/sourcecode]

Onde, no método “insert” presente na classe SQLiteDatabase, possui como parâmetros:

  • O primeiro parâmetro é o nome da tabela a ser inserido;
  • O segundo parâmetro é chamada de coluna dos valores nulos e visa impedir que um registro totalmente nulo seja inserido no banco de dados. O mesmo é devido à limitações do SQL;
  • O terceiro parâmetro é o ContentValues com os valores a serem inseridos.
Atualização de registro
A classe SQLiteDatabase também possui o método “update” para realizar a atualização de dados registrados. Destaque no campo “WHERE” onde é possível utilizar um recurso parecido com o PreparedStatement, disponível em conexões com o JDBC.
[sourcecode language=”java”]
//Atualização do elemento de id == 1
long id = 1;
String _id = String.valueOf(id);
ContentValues valores = new ContentValues();
valores.put("nome", "novo nome");
valores.put("placa", "AAA-1111");
valores.put("ano","2008");

//Primeiro método
db.update("carro", valores, "_id = " + id, null);
//Segundo método
db.update("carro", valores, "_id = ?", new String[]{id});
[/sourcecode]

Onde, o método “update“, disponível na classe SQLiteDatabase, possui como parâmetros: 
  • O nome da tabela em que o registro a ser alterado está armazenado;
  • ContentValues com os novos valores;
  • String que será a condição no caso “WHERE”, disponível no modelo SQL;
  • Array com parâmetros da classe WHERE, caso seja utilizado o segundo método.
Exclusão de registros
A classe SQLiteDatabase também possui o método “delete” para realizar a exclusão do registro que satisfaz a cláusula “WHERE”.
[sourcecode language=”java”]
//Atualização do elemento de id == 1
long id = 1;
String _id = String.valueOf(id);

//Primeiro método
db.delete("carro", valores, "_id = " + id, null);
//Segundo método
db.delete("carro", valores, "_id = ?", new String[]{id});
[/sourcecode]

Onde, o método “delete”, disponível na classe SQLiteDatabase, possui como parâmetros:

  • O nome da tabela em que o registro a ser alterado está armazenado;
  • ContentValues com os novos valores;
  • String que será a condição no caso “WHERE”, disponível no modelo SQL;
  • Array com parâmetros da classe WHERE, caso seja utilizado o segundo método.
Busca de registros
A classe SQLiteDatabase disponibiliza o método “query” onde o seu objetivo é realizar uma consulta no banco de dados. O seu retorno é um Cursor a ser percorrido, e se assemelha com a classe ResultSet utilizada em integrações com o JDBC.
[sourcecode language=”java”]
String nome = "carro";
Cursor c = db.query(TABELA_CARRO, new String[]{"_id", "nome", "placa", "ano"}, "nome=?", new String[]{nome}, null, null, null);
if (c.getCount() > 0)
{
Carro carro = new Carro();
c.moveToFirst();
carro.id = c.getLong(0);
carro.nome = c.getString(1);
carro.placa = c.getString(2);
carro.ano = c.getInt(3);
}
[/sourcecode]

Onde, o método “query” disponível na classe SQLiteDatabase, possui como parâmetros:

  • Valor booleano, parâmetro opcional, em que diz se o retorno deve conter os parâmetros repetidos;
  • Uma String que representa o nome da tabela;
  • Array de String contendo os nomes das colunas de retorno. Caso seja passado null, serão retornadas todas as colunas;
  • String que define a cláusula “WHERE”. Existe também na API, um método de mesmo nome, onde este parâmetro é um vetor de Strings, que constrói automaticamente a cláusula “WHERE”;
  • Array de String que define os argumentos estabelecidos com “?”, caso utilizado uma string para definir a cláusula “WHERE” ou os valores que deverão conter para satisfazer a seleção realizada caso tenha utilizado o vetor de String no parâmetro anterior;
  • String que define, caso passado uma coluna, a operação disponível em SQL “Group By”;
  • String que define, caso passado uma coluna, a operação disponível em SQL “Having”;
  • String que define, caso passado uma coluna, a operação disponível em SQL “Order By”.
Criação do banco de dados via API do Android
Por mais que seja fácil a importação do banco de dados pelo emulador nos dispositivos móveis, durante a realidade das aplicações, não é tão trivial a sua importação. Por isso, é recomendado que o banco de dados seja criado diretamente via código da aplicação. Este tópico é destinado a explicar como é realizada esta criação do banco de dados pelo código.
Para facilitar a criação dos banco de dados via código existe uma classe já implementada pela API do Android chamada SQLiteOpenHelper. O objetivo principal da SQLiteOpenHelper é auxiliar na criação e atualização do banco de dados.
[sourcecode language=”java”]
public classe DBHelper extends SQLiteOpenHelper {
/* Nome do banco de dados */
private static final String DATABASE_NAME = "livro_android";
/* Versão do banco de dados */
public static final int DATABASE_VERSION = 1;
/* Nome da tabela */
private static final String TABLE_NAME = "carro";

public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + "(_id integer primary key autoincrement, nome text not null, placa text not null, ano text not null)");
}

public static DBHelper getInstance(Context context) {
if (instance == null)
instance = new DBHelper(context);
return instance;
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
[/sourcecode]

O exemplo acima é simples e retrata uma classe que herda de SQLiteHelper, mas que supre as necessidades deste exemplo. Em seu código, é possível se observar que:
  • Seu método “onCreate” cria uma única tabela, chamada “carro”, para o nosso exemplo;
  • Existe o método “getInstance” para retornar a instancia do banco de dados;
  • Existe o método “onUpgrade” que possui como funcionalidade, executar uma nova versão do banco de dados. 

Esta classe é a responsável pelo script básico de nosso exemplo. O próximo passo agora é definir o modelo Carro para o manuseio da informação.

[sourcecode language=”java”]
public class Carro {
private int id;
private String nome;
private String placa;
private String ano;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getNome() {
return nome;
}

public void setNome(String nome) {
this.nome = nome;
}

public String getPlaca() {
return placa;
}

public void setPlaca(String placa) {
this.placa = placa;
}

public String getAno() {
return ano;
}

public void setAno(String ano) {
this.ano = ano;
}

public String toString() {
return String.format("%s %s %s", nome, placa, ano);
}
}
[/sourcecode]

O próximo passo é a criação de uma classe que acesse diretamente os modelos, neste caso, o único modelo existente é a classe “Carro”. Por boas práticas de programação, seguindo o modelo de desenvolvimento MVC, dizemos que a classe que acessa o modelo é da categoria DAO (Data Access Object). Chamaremos essa nova classe de CarroDAO.

[sourcecode language=”java”]
public class CarroDAO {
public static final String NOME_TABELA = "carro";
public static final String COLUNA_ID = "_id";
public static final String COLUNA_NOME = "nome";
public static final String COLUNA_PLACA = "placa";
public static final String COLUNA_ANO = "ano";
private SQLiteDatabase dataBase = null;
private static CarroDAO instance;

public static CarroDAO getInstance(Context context) {
if (instance == null)
instance = new CarroDAO(context);
return instance;
}

public CarroDAO(Context context) {
DBHelper persistenceHelper = DBHelper.getInstance(context);
dataBase = persistenceHelper.getWritableDatabase();
}

public void salvar(Carro c) {
ContentValues values = gerarContentValuesVeiculo(c);
database.insert(NOME_TABELA, null, values);
}

public Carro recuperaCarro(int id) {
String str = "_id = ?"?
Cursor cursor = dataBase.query(NOME_TABELA, null, str, new String[]{String.valueOf(id)}, null, null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
int indexID = cursor.getColumnIndex(COLUNA_ID);
int indexNome = cursor.getColumnIndex(COLUNA_NOME);
int indexPlaca = cursor.getColumnIndex(COLUNA_PLACA);
int indexAno = cursor.getColumnIndex(COLUNA_ANO);

String nome = cursor.getString(indexNome);
String ano = cursor.getString(indexAno);
String placa = cursor.getString(indexPlaca);

Carro c = new Carro(id, nome, placa, ano);
return c;
}
return null;
}

public List<Carro> recuperaTodos() {
String queryReturnAll = "SELECT * FROM " + NOME_TABELA;
Cursor cursor = dataBase.rawQuery(queryReturnAll, null);
List<Carro> veiculos = construirVeiculoPorCursor(cursor);
return veiculos;
}

public void deletar(Carro c) {
String[] valoresParaSubstituir = {String.valueOf(c.getId())};
dataBase.delete(NOME_TABELA, COLUNA_ID + " = ?", valoresParaSubstituir);
}

public void editar(Carro c) {
ContentValues valores = gerarContentValuesVeiculo(c);
String[] valoresParaSubstituir = {String.valueOf(c.getId())};
dataBase.update(NOME_TABELA, valores, COLUNA_ID + " = ?", valoresParaSubstituir);
}

public void fecharConexao() {
if (dataBase != null && dataBase.isOpen())
dataBase.close();
}

private List<Carro> construirVeiculoPorCursor(Cursor cursor) {
List<Carro> veiculos = new ArrayList();
if (cursor == null) {
return veiculos;

try {
if (cursor.moveToFirst()) {
do {
int indexID = cursor.getColumnIndex(COLUNA_ID);
int indexNome = cursor.getColumnIndex(COLUNA_NOME);
int indexPlaca = cursor.getColumnIndex(COLUNA_PLACA);
int indexAno = cursor.getColumnIndex(COLUNA_ANO);
int id = cursor.getInt(indexID);

String nome = cursor.getString(indexNome);
String ano = cursor.getString(indexAno);
String placa = cursor.getString(indexPlaca);
Carro c = new Carro(id, nome, placa, ano);
veiculos.add(c);
while (cursor.moveToNext());
}
} finally {
cursor.close();
}
return veiculos;
}

private ContentValues gerarContentValuesVeiculo(Carro c) {
ContentValues values = new ContentValues();
values.put(COLUNA_NOME, c.getNome());
values.put(COLUNA_ANO, c.getAno());
values.put(COLUNA_PLACA, c.getPlaca());
return values;
}
}
[/sourcecode]

Para a realização de testes, basta criar Activities que manuseiem as classes e os métodos implementados neste tutorial.

8 Responses to “Utilizando Banco de Dados em Desenvolvimento Android”

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *