Armazenamento em Banco de Dados em Aplicações Android
Prof. Fellipe Aleixo ([email protected])
Opções de Armazenamento
• Shared Preferences – Armazenamento de pares chave-‐valor
• Internal Memory – UAliza a memória do aparelho
• External Memory – UAliza algum armazenamento externo como cartão SD, USB, etc.
• Banco de Dados
SQLite
• Mecanismo de banco de dados para o qual o Android oferece suporte naAvo
• Obs.: banco de dados pode ser criados e acessados por qualquer classe de uma aplicação (apenas)
O que é SQLite?
• Trata-‐se de uma biblioteca de soQware um motor de banco de dados SQL
• CaracterísAcas: – Self-‐contained – Serverless – Zero-‐configura:on – Transac:onal – Open Source
SQLite no Android
• Nenhum banco de dados padrão é oferecido para a sua aplicação Android
• A própria aplicação precisa criar o banco de dados, tabelas, índices e popular os dados
SQLite no Android
• Para criar e manipular banco de dados a maneira recomendada é criar uma subclasse de SQLiteOpenHelper e definir os métodos: – Construtor – onCreate() – onUpgrade()
• Métodos opcionais: – onOpen() – onDowngrade()
Construtor da Classe Helper
• Exemplo:
– SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
public class DicAonaryOpenHelper extends SQLiteOpenHelper { private staAc final String DATABASE_NAME = “meu_bd”; private staAc final int DATABASE_VERSION = 1;
DicAonaryOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); }
}
Método onCreate() �public class DicAonaryOpenHelper extends SQLiteOpenHelper {
private staAc final String DATABASE_NAME = “meu_bd”; private staAc final int DATABASE_VERSION = 2; private staAc final String DICTIONARY_TABLE_CREATE = “CREATE TABLE DICTIONARY (KEYWORD TEXT,” + “ DEFINITION TEXT);”;
DicAonaryOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DICTIONARY_TABLE_CREATE); }
}
Método onUpgrade() �...
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS DICTIONARY"); onCreate(db); }
...
COMPONENTES GRÁFICOS Uma vez criado o banco de dados, este pode ser acessado a parAr dos
Acessando o Banco de Dados package exemplo.aula; import android.app.AcAvity; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; public class HelloBDAcAvity extends AcAvity {
private SQLiteDatabase database; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); DatabaseHelper helper = new DatabaseHelper(this);
database = helper.getReadableDatabase(); } �}
Manipulando o Banco de Dados
1) UAlizar o método execSQL() – Para executar qualquer SQL que não retorna resultados (INSERT, UPDATE e DELETE)
2) UAlizar os métodos insert(), update() e delete() – Não é necessário trabalhar diretamente com SQL
package exemplo.aula; import android.app.AcAvity; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; public class HelloBDAcAvity extends AcAvity {
private SQLiteDatabase database; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); DatabaseHelper helper = new DatabaseHelper(this); database = helper.getWritebleDatabase(); database.execSQL("INSERT INTO DICTIONARY ”+ “(KEYWORD,DEFINITION) VALUES “+ “('Android','Plataforma para DisposiAvos Móveis')"); }
}
UAlizando Métodos Específicos
• Não uAlizando SQL diretamente �private void processAdd(DialogWrapper wrapper) {
ContentValues values = new ContentValues(2); values.put(DatabaseHelper.TITLE, wrapper.getTitle()); values.put(DatabaseHelper.VALUE, wrapper.getValue()); db.getWritableDatabase().insert("constants", null, values);
}
�private void processDelete(long rowId) { String[] args = { String.valueOf(rowId) }; db.getWritableDatabase().delete("constants", "ID=?", args);
}
Buscando Dados no Banco
1) Através do método rawQuery() – Permite a execução de um uma consulta SQL
2) Através do método query() – Não necessita trabalhar diretamente com SQL – São informados os critérios uAlizados na busca
UAlizando o método rawQuery()
• Informando a consulta SQL completa: �database=db.getReadableDatabase(); Cursor constantsCursor; constantsCursor = database.rawQuery(“SELECT _ID, Atle, value “+
“FROM constants “+ “ORDER BY Atle", null);
UAlizando o método query()
• Parâmetros para compor a consulta: – O nome da tabela – A lista de colunas a serem retornadas – A cláusula WHERE (pode informar parâmetros) – Lista dos valores para subsAtuir os parâmetros – A cláusula GROUP BY – A cláusula HAVING – A cláusula ORDER BY
UAlizando o método query()
– Tabela “widgets” – Colunas desejadas: “ID” e “inventory” – WHERE name = ? – Parâmetro “snicklefritz”
�String[] columns={"ID", "inventory"}; String[] parms={"snicklefritz"}; Cursor result = db.query("widgets", columns, "name=?", parms,
null, null, null);
Manipulando Cursores
• O resultado de uma consulta é um cursor – Apontador para os registros resultantes – Permite a navegação pelos resultados
Manipulando Cursores
• Métodos para manipulação de um cursor: – getCount() à número de registros retornados – Navegar pelos registros – moveToFirst(), moveToNext() e isAPerLast()
– getColumnNames() e getColumnIndex() à recupera nomes e posição das culunas
– requery() à reexecuta a consulta – close() à libera os recursos
Manipulando Cursores �Cursor result = db.rawQuery(“SELECT ID, name, inventory “+
“FROM widgets", null); while (!result.moveToNext()) {
int id = result.getInt(0); String name = result.getString(1); int inventory = result.getInt(2); // Faz algo com os valores ...
} result.close();
PRATICAR Vamos
Construir uma Aplicação Exemplo
• Aplicação: agenda de contatos – Um contato possui nome, e-‐mail e telefone
– Os contatos devem ser armazenados no banco
Passo-‐a-‐Passo
1) Criar um projeto com o nome de “Contatos” – Pacote: exemplo.contatos – AAvidade: ContatosAcAvity
2) Criar uma classe com o nome “DbHelper” – Responsável por criar o banco de dados – Estende a classe SQLiteOpenHelper
�import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.uAl.Log; public class DbHelper extends SQLiteOpenHelper { ... }
Passo-‐a-‐Passo
3) Definição de constantes private staAc final String DATABASE_NAME = “contatosDB”; private staAc final int DATABASE_VERSION = 1; public staAc final String TABLE_NAME = ”contatos”; public staAc final String ID = "_id"; public staAc final String NOME = "nome"; public staAc final String EMAIL = "email"; public staAc final String TELEFONE = "telefone"; public staAc final String FOTO = "foto"; private staAc 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);";
Passo-‐a-‐Passo
4) Definição do construtor public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); }
Passo-‐a-‐Passo
5) Definição dos métodos onCreate() e onUpgrade()
@Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVers, int newVers) {
Log.w(DbHelper.class.getName(), "Upgrading database from “+oldVers+” to “+newVers);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db);
}
Passo-‐a-‐Passo
6) Criar a classe DBAdpter para concentrar o trabalho com o banco de dados
import java.io.ByteArrayOutputStream; import java.uAl.ArrayList; import java.uAl.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLExcepAon; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.BitmapFactory; public class DBAdapter { ... }
Passo-‐a-‐Passo
7) Declarar atributos e construtor da classe DBAdpter
private SQLiteDatabase database; private DbHelper dbHelper; private String[] allColumns = { DbHelper.ID, DbHelper.NOME, DbHelper.EMAIL, DbHelper.TELEFONE, DbHelper.FOTO}; public DBAdapter(Context context) {
dbHelper = new DbHelper(context); }
Passo-‐a-‐Passo
8) Definir um método que insere um contato no banco de dados – Veja no próximo slide
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); Cursor cursor = database.query(DB.TABLE_NAME, allColumns, DB.ID + " = " + insertId, null,null, null, null); cursor.moveToFirst(); return cursorToContato(cursor);
}
Passo-‐a-‐Passo
9) Criar uma classe Contato com os atributos, construtor com parâmetros e métodos acessadores e modificadores
10) Definir um método para remover um contato public void removeContato (int idContato) {
database.delete(DbHelper.TABLE_NAME, DbHelper.ID + " = " + idContato, null);
}
Passo-‐a-‐Passo
11) Definir um método para retornar um contato passando um cursos para o mesmo
private Contato cursorToContato(Cursor cursor) { byte[] blob = cursor.getBlob(cursor.getColumnIndex(DB.FOTO)); Bitmap bmp = BitmapFactory.decodeByteArray(blob, 0, blob.length); Contato contato = new Contato(cursor.getLong(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), bmp); return contato;
}
Passo-‐a-‐Passo
12) Definir um método retornando os contatos public List<Contato> getContatos() {
Cursor cursor = database.rawQuery("select * from contatos", null); ArrayList<Contato> contatos = new ArrayList<Contato>(); cursor.moveToFirst(); while(!cursor.moveToNext()) { Contato atual = new Contato(cursor.getLong(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), bmp); contatos.add(atual); } return contatos;
}
Passo-‐a-‐Passo
13) Definir um método que retorna um contato passando o idenAficador do mesmo
public Contato getContato (int idContato){ Cursor cursor = database.query(DB.TABLE_NAME, allColumns, DB.ID + " = " + idContato, null,null, null, null); cursor.moveToFirst(); return cursorToContato(cursor);
}
Passo-‐a-‐Passo
14) Crie as classes de Layout para operando com estas classes criada implemente a funcionalidade de agenda de contatos...