Tutorial: Utilização do sqlite no Android (Parte I)
Por Mário Baltazar para o Pplware
Tutorial realizado no âmbito do Mestrado em Computação Móvel do Instituto Politécnico da Guarda na Unidade Curricular de Seminário
A plataforma Android foi introduzida no mercado pela Google em 2007 e é composta por um sistema operativo embebido e um conjunto de aplicações que integram com a plataforma. Além das várias inovações implementadas, o Android traz também suporte nativo para o SQLite. O SQLite é uma pequena biblioteca, desenvolvida em linguagem C, que implementa um amplo subconjunto do standard SQL 92, sendo a sua reputação proveniente da combinação do motor de base de dados com a interface dentro de uma única biblioteca. As aplicações que usam SQLite podem ter assim acesso a uma base de dados racional SQL, sem a necessidade de correrem processos RDBMS (relational database management system) em separado e sem grandes overheads. O SQLite foi desenvolvido em 2000 e é actualmente uma base de dados amplamente adoptada em dispositivos móveis, suportando até 2 TB de dados.
Este artigo será dividido em duas partes e hoje vamos começar por ensinar como criar uma pequena aplicação para registo de contactos, sendo esses contactos guardados na base dados sqlite.
Vamos então começar com o desenvolvimento da aplicação, usando para isso a ferramenta de desenvolvimento eclipse.
1 – Criar Projecto Criação de um novo projecto no Eclipse com o nome: “Contactos” File > New > Other > Android/Android Project
2 – Criar uma nova classe com nome DbHelper Esta classe será responsável por criar a base de dados no momento em que a aplicação é instalada (método onCreate) e actualizá-la para novas versões(método onUpgrade).
2.1 - A classe DB expande a classe SQLiteOpenHelper, esta fornece os métodos getReadableDatabase() e getWriteableDatabase(), que permitem aceder à base dados SQLiteDatabase quer para ler quer para escrever.
public class DbHelper extends SQLiteOpenHelper { } |
2.2 - Adicionar os imports necessários para a classe:
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; |
2.3 - Adicionar as constantes necessárias:
private static final int DATABASE_VERSION = 1; public static final String ID = "_id"; public static final String NOME = "nome"; public static final String EMAIL = "email"; public static final String TELEFONE = "telefone"; public static final String FOTO = "foto"; private static final String DATABASE_CREATE = "create table " + TABLE_NAME + "( " + ID + " integer primary key autoincrement, " + NOME + " text not null, " + EMAIL + " text not null, " + TELEFONE+" text not null" + ", "+ FOTO +" BLOB);"; |
2.4 - Fazer @override das classes necessárias:
@Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(DbHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } |
2.5 - No final a classe terá um aspecto parecido com o seguinte:
public class DbHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "contactos4.db"; public static final String TABLE_NAME = "contactos2"; private static final int DATABASE_VERSION = 1; public static final String ID = "_id"; public static final String NOME = "nome"; public static final String EMAIL = "email"; public static final String TELEFONE = "telefone"; public static final String FOTO = "foto"; private static final String DATABASE_CREATE = "create table " + TABLE_NAME + "( " + ID + " integer primary key autoincrement, " + NOME + " text not null, " + EMAIL + " text not null, " + TELEFONE+" text not null" + ", "+ FOTO +" BLOB);"; public DbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(DbHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } |
4- Criar nova classe DBAdapter que será a classe base para trabalhar com SQLite. Esta irá permitir abrir, fechar, fazer queries e actualizar a base de dados. 4.1 - Criar nova classe DBAdapter
public class DBAdapter { } |
4.2 - Adicionar os imports necessários para a aplicação:
import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.BitmapFactory; |
4.3 - Adicionar os Atributos necessários para a classe:
private SQLiteDatabase database; private DbHelper dbHelper; private String[] allColumns = { DbHelper.ID, DbHelper.NOME, DbHelper.EMAIL, DbHelper.TELEFONE, DbHelper.FOTO}; |
4.4 - Declarar construtor da classe que irá inicializar uma instância da classe DbHelper.
public DBAdapter(Context context) { dbHelper = new DbHelper(context); } |
Um Context é um handle para o sistema, que fornece serviços como resources, acesso a base de dados e preferências. O contexto da aplicação (application context) é o repositório central para a funcionalidade de todas as aplicações de nível superior no Android. Usa-se este contexto quando queremos aceder a configurações e recursos compartilhados entre as várias janelas (activities) da aplicação.
4.5 - Criar método para criar um novo contacto na base de dados, este irá retornar um objecto Contacto.
public Contacto createContacto(String nome, String email, String telefone, Bitmap foto) { ContentValues values = new ContentValues(); values.put(DB.NOME, nome); values.put(DB.EMAIL,email); values.put(DB.TELEFONE,telefone); ByteArrayOutputStream baos = new ByteArrayOutputStream(); foto.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] photo = baos.toByteArray(); values.put(DB.FOTO, photo); long insertId = database.insert(DB.TABLE_NAME, null, values); // To show how to query Cursor cursor = database.query(DB.TABLE_NAME, allColumns, DB.ID + " = " + insertId, null,null, null, null); cursor.moveToFirst(); return cursorToContacto(cursor); } |
Os cursores são “apontadores de dados” da base de dados – ou seja, uma interface que permite o acesso aos dados retornados pela query. O objecto ContentValues permite definir os valores a inserir.
4.6 - Método para eliminar um contacto:
public void EliminaContacto (int idContacto){ database.delete(DbHelper.TABLE_NAME, DbHelper.ID + " = " + idContacto, null); } |
4.7 - Método para devolver um Contacto passando como parâmetro um cursor.
private Contacto cursorToContacto(Cursor cursor) { byte[] blob = cursor.getBlob(cursor.getColumnIndex(DB.FOTO)); Bitmap bmp = BitmapFactory.decodeByteArray(blob, 0, blob.length); Contacto contacto = new Contacto(cursor.getLong(0),cursor.getString(1),cursor.getString(2), cursor.getString(3),bmp); return contacto; } |
4.8 - Método para devolver todos os contactos da tabela:
public Cursor getContactos(){ Cursor cursor = database.rawQuery("select _id, nome,telefone,foto from contactos2", null); return cursor; } |
4.9 - Método que devolve o contacto passando como parâmetro o id do contacto pretendido:
public Contacto getContacto (int idContacto){ Cursor cursor = database.query(DB.TABLE_NAME, allColumns, DB.ID + " = " + idContacto, null,null, null, null); cursor.moveToFirst(); return cursorToContacto(cursor); } |
Terminamos agora a criação das classes auxiliares para trabalhar com a base de dados, no próximo tutorial iremos criar os layouts e utilizar estas classes para guardar os dados na base de dados.
Este artigo tem mais de um ano
@Of Topic.
Procuro uma aplicação que me informe através de um icon na barrasuperior que a chamada que estou a receber é uma chamada reencaminhada de outro telefone se assim for o caso.
É que tenho o meu numero fixo encaminhado para o móvel e por vezes atendo chamadas que até nem precisava de atender mas como não sei se é reencaminhada ou não tenho de atender.
Na StockRom do meu SGS há um popup a avisar da chamada reencaminhada mas apenas aparece ao primeiro toque o que a torna inutil uma vez que não estou sempre a olhar para o ecra do mesmo.
Algume conhece uma? Alguem se sente capaz de desenvolver algo do género?
https://play.google.com/store/apps/details?id=de.duenndns.forwardedcall&feature=more_from_developer#?t=W251bGwsMSwxLDEwMiwiZGUuZHVlbm5kbnMuZm9yd2FyZGVkY2FsbCJd
Muito, mas mesmo muito, obrigado!!!
Vou já testar essa aplicação.
Excelente! Podiam fazer mais tutoriais de como programar em android!
Parabéns pela iniciativa. Continue o bom trabalho e a desenvolver estes tutoriais, como interessado em programar android agradeço-lhe.
Espetaculo! Isto vai me ser tão útil! 🙂
Excelente tutorial 🙂
Em vez de usarem SQLite cru e duro eu aconselho usarem o ORMLite (ormlite.com).
É uma biblioteca de Object Relational Mapping muito fácil de usar, leve e extremamente poderosa. Para não falar que o código de acesso/escrita na base de dados em sqlite fica extremamente simples e fácil de utilizar.
Se quiserem até podia escrever um artigo para principiantes.
Neste momento estamos a utilizar esta biblioteca na nossa app que conta com um modelo de dados bastante complexo: https://play.google.com/store/apps/details?id=com.pt.stt.h19
Interessante também. Vou analisar melhor
Eu também estou a usar o ormlite e das alternativas que testei pareceu-me sem dúvida a melhor.
Super util e bem explicado, gostei muito, parabens
Será possivel meter um tutorial de como usar uma base de dados nossa?
Ou seja, ter uma BD já em sqlite, e só fazer o import e leitura da BD?
Já estive a ler uns tutorias, mas sou ainda muito verde nisto de programar.
Obrigado desde já!
Como adicionar campos booleanos numa base dados sqlite? É que o formato booleano, penso que não existe, tal como existe o SimpleDateFormat, etc, etc.
Se alguém souber agradeço, já que está relacionado com o tema.
É para utilizar num campo que em caso afirmativo aparecerá “Yes” em caso negativo aparecerá “No”.
Obrigado.
Eu utilizo uma string para booleanos no android. Yes ou No são as duas alternativas. No momento de avaliar a expressão faz-se um compare(“yes”).
Ex: cursor2.getString(cursor2.getColumnIndex(“checkComprado”)).equals(“true”)
Obrigado vou tentar dessa maneira.
Obrigado de novo.
Também poderás usar um inteiro e utilizas 0 para negativo e 1 para positivo por exemplo. Defines o que será mais facil de usar par ti.
Uma grande pergunta já que estão a falar de SQLite no Android, existe alguma plataforma como o Core Data no iPhone, é que desta maneira é basicamente um wrapper a volta do SQLite, queria se havia uma abstracção como o Core Data.
O que tu queres é uma biblioteca de ORM – Object Relational Mapping.
Eu uso o ORMLite e aconselho vivamente. É muito mais fácil de usar que o SQLite nativo do Android e tem um poder brutal.
Atenção que nem sempre o recurso a ORMs é a melhor solução. Estamos a desenvolver para dispositivos móveis e é necessário ter em conta factores como performance e utilização de bateria.
ORMlite tem uma footprint mt pequena mas mesmo assim as vezes é preciso analisar bem o que se quer fazer.
De resto, ORMLite ->Gosto
Muito bom o post, você esta de parabéns.
Você fala que a classe DbHelper, serve para criar o banco de dados no momento em que a app for instalada. Após o banco for criado as informações são mantidas nele mesmo após encerrar o app ou até mesmo após reiniciar o aparelho?
Claro, é para isso que serve uma base de dados. Persistência dos dados.
Muito bem Mário!
Gostei muito do tutorial. Como podes ver pelos posts, podes continuar a desenvolver o tema 😉
Não pares.
Muito obrigado.
Vou continuar 🙂
Já cá tenho a parte 2 🙂
Boas, bom tuturial 🙂
onde esta esse parte 2? 😛
Falta um pouco mais de comentarios no codigo.. torna-se um pouco complicado para quem está a começar..
Concordo plenamente. Percebi isso quando fui tentar implementar, embora não tão leigo assim. Imagine um sem noção alguma? Hehehe
Excelente tutorial, estou com um probleminha quando tendo fazer em uma query o where e neste where eu quero pegar os tuplas aonde tenho “path=”+str, e str é igual a uma string deste formato “/mnt/sdcard/folder/teste/”
porém quando eu tento fazer isso aparece um erro no logcat, informando erro perto do ‘/’, já fiz teste com strings e não tive problemas, porém quando eu coloco ‘/’ dispara erro.
Alguém pode me ajudar?
Olá,
Todas as linhas que tem DB.alguma coisa dá erro, como por exemplo:
values.put(DB.NOME, nome);
Estou començando agora, podem me ajudar? valeu
Tenho Problema , e tambem nos contactos e Cursor
Tbm tive nos mesmo pontos que citou, marcou em vermelho
Não sei se estou distraído ou não mas onde é que surge a classe Contacto? Não encontro em parte alguma o código. Talvez seja o passo 3 que saltaram (passaram do 2.5 para o 4). Se puderem disponibilizar agradecia. Cumprimentos
E ae galera, se vcs acharam que tem alguns passos incompletos, aconselho a ir para a parte 2 e puxar o código lá.
https://pplware.sapo.pt/tutoriais/tutorial-utilizao-do-sqlite-no-android-parte-ii/
Dois erros que eu verifiquei nessa parte:
– o DB que ele chama era para ser o dbHelper
– Na classe contato dele, existe um campo long para o _id
(a classe contatos somente tem os contrutores e os getters/setters, mas novamente, caso estejam com dúvida, aconselho a ir para a próxima parte e verificar o código)
Parabéns pelo post e Ricardo, seu comentário tb ajudou.
obrigado
Parabéns pelo tutorial, aproveitei muito.
Apenas me restou uma dúvida, no caso meu BD tem 3 tabelas, posso criar as três utilizando a mesma classe DbHelper?
Ficaria assim:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_CAMINHOES);
db.execSQL(CREATE_PRODUTOS);
db.execSQL(CREATE_ACESSORIOS);
}
Parabéns pelo tutorial!
Alguma ideia do código para o método “editar” um contacto?
Infelizmente essa parte não está contemplada no tutorial.
Cumprimentos.
Eu ando lendo muito e surgem muitas dúvidas.
Minha dúvida é como eu faço para criar um banco de de Dados com informações só para serem acessadas(consultadas)
Por exemplo tenho 3 spinners e um botão. Vou colocar um exemplo
na 1º Spinner eu teria opções de escola, hospitais, praças (Lugares Públicos)…
na 2º Spinner eu teria as opções de zonas da cidade,( zona 1, zona2, zona3..)
na 3º spinner os principais os bairros da cidade( bairro A, bairro B…)
se a spinner 1 eu escolher Escola
e a spinner 3 eu escolher o Bairro A,
e a pessoa clicar no botão pesquisar
como eu faço para na próxima tela apresentar todas as escolas do Bairro A ??
Não é pra inserir nada, queria saber como faz um banco de dados apenas para consultar dados inseridos!
De modo que quando alguém selecionar o Bairro A, na tela seguinte faria uma query sobre esses dados (ex. select * from escola where bairro = ‘A’)
Como eu faço isso??
Me tira uma dúvida. Eu criei um sqlite por fora e tô colocando ele em na pasta assets pra depois copia-lo quando o aplicativo for instalado. Só que ele copia pra pasta certa o banco mas os atributos que estavam antes rw-rw-rw agora estão rw-rw- e com isso não consigo acessar o banco. Sabe o porque do arquivo ter perdido essas permissões?
Ainda não testei, mas gostaria de colocar uma questão.
Se a base de dados tiver mais do que uma tabela, como se faz?
Obrigado
Olá. Gostei deste tutorial, pois cada etapa da implementação está bem explicada. Para iniciantes em Android, como eu, é uma mão na roda!
No entanto surgiu uma dúvida com relação aos tópicos 4.5 e 4.9. Eu não entendi o uso do “DB.”
(ContentValues values = new ContentValues();
values.put(DB.NOME, nome);
values.put(DB.EMAIL,email);
values.put(DB.TELEFONE,telefone);)
O que é o “DB” afinal? de onde ele surgiu?
Agradeço desde já!
MRFerrari.
Olá,
Achei bacana o tutorial, bem explicado parabéns.
Contudo, notei que não foi implementado nenhum método para alteração de dados do contato, passando por exemplo o id ou o nome do contato, teria como fazer essa implementação?
Grato.
Olá,
Me tira uma duvida?… como eu faço pra carregar um listView com dados do banco SQLite sem a minha tabela ter o campo “_id”
a tabela tem os campos “nome”,”numeroContrato”,”status”
se eu colocar o “_id” da certo na hora de fazer o listView.setAdapter(adapter) , mas queria arrumar uma forma de não colocar esse campo “_id” na minha tabela.
Preciso da ajuda de vocês…
muito obrigado!
Ótimo tutorial! esta de parabéns!
Utilizei esse tutorial e achei fantástico, fiz uma aplicação e funciona direitinho, porém dá esse erro: (Finalizing a Cursor that has not been deactivated or closed. database = /data/data/com.contactos/databases/contactos4.db, table = null, query = select _id, nome,telefone,foto from contactos2). Alguém poderia me ajudar a corrigi-lo? Desde já, obrigado.
Olá a todos. Estou com dificuldade para instalar o eclipse…! alguém de me pode ajudar? obrigado.
Boa noite, está a tentar instalar o eclipse para programar para Android?
Sim! Podes-me ajudar?
Olá de novo! Alguém para ajudar na instalação do eclipse ou outra aplicação para programar em android? Obrigado.
Olá Keyros. O Eclipse na verdade não precisa de instalação, é só baixar o zip, descompactar os arquivos em uma pasta de sua preferência, criar um atalho e rodar. Entretanto é necessário configurar o JDK e as variáveis de ambiente, para isso você pode dar uma olhada aqui: http://pt.stackoverflow.com/q/8708/3117 Se esse tópico não responder a sua pergunta você pode criar uma nova pergunta nesse site que com certeza te responderão bem rápido. Abraço;
Obrigado Matheus, vou-me tentar orientar…
Em 2.3 está faltando a constante TABLE_NAME :
public static final String TABLE_NAME = “contactos2”;