Upload
matheus-augusto
View
45
Download
0
Embed Size (px)
Citation preview
Criando e usando Banco de Dados em uma Aplicação AndroidBom galera, vamos falar um pouco sobre como criar e utilizar um banco de dados em uma aplicação
android. Por padrão, o banco de dados utilizado é o SQLite. Imagino que você deve estar se
perguntando, mas Eduardo, o que é o SQLite?
Em uma breve explicação, o SQLite é uma biblioteca em linguagem C, open source, que implementa
um banco de dados SQL embutido, ou seja, não tem processo servidor separado, lendo e escrevendo
diretamente no arquivo de banco de dados no disco. O android utiliza o SQLite por ser uma biblioteca
leve, utilizando dentre 250kb a 500kb, sendo multi-plataforma, onde você pode copiar livremente um
banco de dados entre sistemas de 32bits e 64bits.
O SQLite está disponível em todos os dispositivos android, utilizá-lo não requer qualquer configuração
ou administração de banco de dados, você precisa somente definir os comandos SQL para criar e
atualizar o banco. Depois disso, o banco de dados é gerenciado automaticamente para você pela
plataforma Android. Quando criado, o banco de dados por padrão é armazenado no
diretório /data/data/<nome-do-pacote-utilizado>/databases/nome-do-arquivo.sqlite.
Bom, vamos à parte divertida do post e o motivo de estarem lendo até agora, hora do Hands On!
package com.agenda; import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteCursor;import android.database.sqlite.SQLiteCursorDriver;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.database.sqlite.SQLiteQuery;import android.util.Log; public class ContextoDados extends SQLiteOpenHelper { /** O nome do arquivo de base de dados no sistema de arquivos */ private static final String NOME_BD = "Agenda"; /** A versão da base de dados que esta classe compreende. */ private static final int VERSAO_BD = 2; private static final String LOG_TAG = "Agenda"; /** Mantém rastreamento do contexto que nós podemos carregar SQL */ private final Context contexto; public ContextoDados(Context context) { super(context, NOME_BD, null, VERSAO_BD); this.contexto = context; } @Override public void onCreate(SQLiteDatabase db) { String[] sql = contexto.getString(R.string.ContextoDados_onCreate).split("\n"); db.beginTransaction(); try
{ // Cria a tabela e testa os dados ExecutarComandosSQL(db, sql); db.setTransactionSuccessful(); } catch (SQLException e) { Log.e("Erro ao criar as tabelas e testar os dados", e.toString()); } finally { db.endTransaction(); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(LOG_TAG, "Atualizando a base de dados da versão " + oldVersion + " para " + newVersion + ", que destruirá todos os dados antigos"); String[] sql = contexto.getString(R.string.ContextoDados_onUpgrade).split("\n"); db.beginTransaction(); try { ExecutarComandosSQL(db, sql); db.setTransactionSuccessful(); } catch (SQLException e) { Log.e("Erro ao atualizar as tabelas e testar os dados", e.toString()); throw e; } finally { db.endTransaction(); } // Isto é apenas didático. Na vida real, você terá de adicionar novas colunas e não apenas recriar o mesmo banco onCreate(db); } /** * Executa todos os comandos SQL passados no vetor String[] * @param db A base de dados onde os comandos serão executados * @param sql Um vetor de comandos SQL a serem executados */ private void ExecutarComandosSQL(SQLiteDatabase db, String[] sql) { for( String s : sql ) if (s.trim().length()>0) db.execSQL(s); } /** Retorna um ContatosCursor ordenado * @param critério de ordenação */ public ContatosCursor RetornarContatos(ContatosCursor.OrdenarPor ordenarPor) { String sql = ContatosCursor.CONSULTA + (ordenarPor == ContatosCursor.OrdenarPor.NomeCrescente ? "ASC" : "DESC"); SQLiteDatabase bd = getReadableDatabase(); ContatosCursor cc = (ContatosCursor) bd.rawQueryWithFactory(newContatosCursor.Factory(), sql, null, null); cc.moveToFirst();
return cc; }
public long InserirContato(String nome, String telefone, String endereco) { SQLiteDatabase db = getReadableDatabase(); try { ContentValues initialValues = new ContentValues(); initialValues.put("Nome", nome); initialValues.put("Telefone", telefone); initialValues.put("Endereco", endereco); return db.insert("Contatos", null, initialValues); } finally { db.close(); } } public static class ContatosCursor extends SQLiteCursor { public static enum OrdenarPor{ NomeCrescente, NomeDecrescente } private static final String CONSULTA = "SELECT * FROM Contatos ORDER BY
Nome "; private ContatosCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
String editTable, SQLiteQuery query) { super(db, driver, editTable, query); } private static class Factory implements SQLiteDatabase.CursorFactory { @Override public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
String editTable, SQLiteQuery query) { return new ContatosCursor(db, driver, editTable, query); } } public long getID() { return getLong(getColumnIndexOrThrow("ID")); } public String getNome() { return getString(getColumnIndexOrThrow("Nome")); } public String getEndereco() { return getString(getColumnIndexOrThrow("Endereco")); } public String getTelefone() { return getString(getColumnIndexOrThrow("Telefone"));
} }}
A classe java ContextoDados é a classe que está criando o banco de dados e suas tabelas, esta
classe está herdando de SQLiteOpenHelper(classe auxiliar para criação de banco de dados e
gerenciamento de versão), sobrescrevendo (@Override) os métodos onCreate e onUpgrade. Como
podemos ler no post do nosso amigo Marlon Ávila sobre Ciclo de Vida Android, o método
onCreate é chamado automaticamente quando a aplicação é aberta pela primeira vez, tendo como
tarefa criar a base de dados. Como todas as aplicações podem ter novas versões, utilizamos o
método onUpdate para fazer a atualização da base de dados. O papel do método
ExecutarComandosSQL é facilitar a execução dos comandos SQL.
No Android é possível fazer a personalização de cursores, sendo cada cursor personalizado uma
classe dentro da classe ContextoDados, e essa personalização foi utilizada na classe ContatosCursor,
para reduzir a dependência de código, escondendo a informação de operação de dados específicas
dentro deste cursor personalizado. O método RetornarContatos tem a função de retornar um
ContatosCursor preenchido com os contatos do banco de dados, sendo possível ordenar os contatos
por Nome em ordem crescente ou decrescente.
Como o foco neste post é a criação e utilização de banco de dados, foi feita uma interface simples, se
quiser aprofundar no assunto de Layouts para Android, visite o post do nosso amigo Odair Fernandes sobre o assunto.
Abaixo temos um anexo de como a tela principal ficou, e o código XML utilizado para deixá-la desta
maneira, nesta tela foram usados duas TextView, uma mostrando um título para a página e outra para
mostrar os contatos salvos no banco e um botão que irá direcionar para a tela do formulário, onde
serão informados os dados dos usuários:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/contatos"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/listaContatos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nenhum contato cadastrado." />
<Button
android:id="@+id/btnNovo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Novo Cadastro" />
</LinearLayout>
Agora veremos como ficará a Activity principal que por default recebe o nome de MainActivity e em
seguida falaremos sobre os métodos listados nela.
package com.agenda;
import com.agenda.ContextoDados.ContatosCursor;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
Button btnSalvar, btnCancelar, btnNovo;
EditText txtNome, txtEndereco, txtTelefone;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CarregarInterfaceListagem();
}
public void CarregarInterfaceListagem()
{
setContentView(R.layout.main);
//configurando o botão de criar novo cadastro
btnNovo = (Button)findViewById(R.id.btnNovo);
btnNovo.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
CarregarInterfaceCadastro();
}});
CarregarLista(this);
}
public void CarregarInterfaceCadastro()
{
setContentView(R.layout.cadastro);
//configurando o botão de cancelar cadastro
btnCancelar = (Button)findViewById(R.id.btnCancelar);
btnCancelar.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
CarregarInterfaceListagem();
}});
//configurando o formulário de cadastro
txtNome = (EditText)findViewById(R.id.txtNome);
txtEndereco = (EditText)findViewById(R.id.txtEndereco);
txtTelefone = (EditText)findViewById(R.id.txtTelefone);
//configurando o botão de salvar
btnSalvar = (Button)findViewById(R.id.btnSalvar);
btnSalvar.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
SalvarCadastro();
}});
}
public void SalvarCadastro()
{
ContextoDados db = new ContextoDados(this);
db.InserirContato(txtNome.getText().toString(),
txtTelefone.getText().toString(), txtEndereco.getText().toString());
setContentView(R.layout.main);
CarregarLista(this);
}
public void CarregarLista(Context c)
{
ContextoDados db = new ContextoDados(c);
ContatosCursor cursor =
db.RetornarContatos(ContatosCursor.OrdenarPor.NomeCrescente);
for( int i=0; i <cursor.getCount(); i++)
{
cursor.moveToPosition(i);
ImprimirLinha(cursor.getNome(), cursor.getTelefone(),
cursor.getEndereco());
}
}
public void ImprimirLinha(String nome, String telefone, String endereco)
{
TextView tv = (TextView)findViewById(R.id.listaContatos);
if(tv.getText().toString().equalsIgnoreCase("Nenhum contato
cadastrado."))
tv.setText("");
tv.setText(tv.getText() + "\r\n" +"Nome: "+ nome + "\n " +"Telefone: "+
telefone + "\n"+ "Endereço: "+endereco);
}
}
Esta classe concatena as strings em um TextView para simular as listagens das informações que são
trazidas no banco de dados. Até aqui podemos apenas efetuar uma busca no banco de dados e listar
nesta classe.
Agora chegou a parte divertida do nosso post, iremos fazer a escrita no banco de dados. Para isso,
vamos retornar um pouco para nossa classe ContextoDados, olhando este trecho de código, veremos
como inserir um registro no banco de Contatos:
public long InserirContato(String nome, String telefone, String endereco)
{
SQLiteDatabase db = getReadableDatabase();
try
{
ContentValues initialValues = new ContentValues();
initialValues.put("Nome", nome);
initialValues.put("Telefone", telefone);
initialValues.put("Endereco", endereco);
return db.insert("Contatos", null, initialValues);
}
finally
{
db.close();
}
}
Veremos a seguir uma tela simples e seu código XML, que cria um pequeno formulário de cadastro de
usuários, contendo apenas três TextView para informar os campos a serem preenchidos, três EditText
onde o usuário informará as informações e dois botões, um que irá salvar as informações no banco, e
outro que voltará para a tela principal sem efetuar nenhuma alteração:
?xml version="1.0" encoding="utf-8"?>
AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/lblNome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="8dp"
android:layout_y="9dp"
android:text="@string/lblNome"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/lblTelefone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="7dp"
android:layout_y="52dp"
android:text="@string/lblTelefone"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/lblEndereco"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="8dp"
android:layout_y="95dp"
android:text="@string/lblEndereco"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/txtNome"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_x="78dp"
android:layout_y="8dp"
android:inputType="textPersonName" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/txtTelefone"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_x="78dp"
android:layout_y="50dp"
android:inputType="phone" />
<EditText
android:id="@+id/txtEndereco"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_x="78dp"
android:layout_y="93dp"
android:inputType="textPostalAddress" />
<Button
android:id="@+id/btnSalvar"
android:layout_width="82dp"
android:layout_height="wrap_content"
android:layout_x="173dp"
android:layout_y="142dp"
android:text="@string/btnSalvar" />
<Button
android:id="@+id/btnCancelar"
android:layout_width="92dp"
android:layout_height="wrap_content"
android:layout_x="78dp"
android:layout_y="141dp"
android:text="Cancelar" />
</AbsoluteLayout>
E esta será a tela inicial já com os dados recebidos:
Link para download do projeto : Agenda