Banco de dados para Android

Banco de dados para android sqlite3

SQLite3

Um Banco de dados é muito útil para qualquer sistema de grande ou pequeno porte, a não ser que seu sistema lida apenas com dados simples, não utilizando de um banco para armazenar informações.

O Android usa o banco de dados SQLite que é open-source, o SQLite é muito utilizado em aplicações populares. Outros exemplo de quem utiliza o SQLite é Mozilla Firefox e iPhone.

No Android o banco de dados que você cria em uma aplicação só é acessível para si mesma, a não ser que você utiliza um provedor de conteúdo (assunto a ser discutido em outro post), uma vez criado o banco de dados, ele é armazenado no diretório “/data/data/{nome do pacote}/databases/{nome do banco}”, alem de gerenciar o banco por código você pode faze-lo pelo adb(clique para saber mais) utilizando a ferramenta sqlite3.

Exemplo:

$ adb -s emulator-5554 shell
# sqlite3 /data/data/zarelli.exemplo/databases/banco
SQLite version 3.3.12
Enter ".help" for instructions
.... enter commands, then quit...
# sqlite> .exit

A Aplicação

Vou implementar um exemplo bem simples sem a utilização de interface, só com visualização no Log. Primeiro vamos definir nosso banco de dados, vou fazer o SQL em um arquivo (diferente de muitos exemplos) e depois carregar no código, eu prefiro assim pois acredito que tem mais controle e fica mais organizado. Após sera implementado as classes de controle do banco e por fim vamos utiliza-las.

Defini a estrutura dos pacotes da seguinte maneira (com suas classes):

No arquivo create.sql vamos definir as tabelas de nosso database:

CREATE TABLE usuarios_tbl (
 id_usuarios INTEGER PRIMARY KEY autoincrement,
 usuario varchar(45) NOT NULL ,
 senha varchar(45) NOT NULL,
 nome_completo varchar(45) NOT NULL
);

Após a definição do banco vamos criar a classe de mais baixo nível, a BancoManager.java. Essa classe vai ser uma classe abstrata responsável em criar o banco e ter o controle de versão dele, iremos utilizar como classe pai SQLiteOpenHelper.java que é nativa do Android e tem a finalidade de gerenciamento.

public abstract class BancoManager extends SQLiteOpenHelper {

    protected Context context;

    public BancoManager(Context context, String nome, int versao) {
        super(context, nome, null, versao);
        this.context = context;
    }

    public abstract void onCreate(SQLiteDatabase bd);

    public abstract void onUpgrade(SQLiteDatabase bd, int versaoAtual, int versaoNova);

    /** Atravez do id do arquivo sql será gerado o banco de dados.
     *
     * @param fileID
     * @param bd
     * @throws IOException
     */
    protected void byFile(int fileID, SQLiteDatabase bd) throws IOException {
        StringBuilder sql = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(fileID)));
        String line;
        while ((line = br.readLine()) != null) {
            line = line.trim();
            if (line.length() > 0) {
                sql.append(line);
                if (line.endsWith(";")) {
                    bd.execSQL(sql.toString());
                    sql.delete(0, sql.length());
                }
            }
        }
    }
}

Como vemos essa classe não faz nada se ninguém implementar, nela temos um método abstrato onCreate e onUpgrade, ambas precisam ser implementadas para que a coisa toda funcione, o método onCreate ficará responsável em criar o banco, caso o banco já exista nada será alterado, o método onUpgrade é utilizado para atualizar a base da dados, caso alguma tabela seja alterada, mas nada acontece automaticamente devemos implementa-la de forma correta, esse método será chamado automaticamente caso a versão que é passada no contrutor sejá alterada.

Antes de implementar a BancoManager, vamos implementar a classe Banco.java, nela podemos abstrair muita informação, fiz ela o mais simples possível, mas podemos tratar os insert,update,delete,select nesta classe de uma forma bem abstrata para que haja a melhor orientação possível. Entenda que essa classe sera responsável em gerenciar a conexão do banco.

public class Banco {

    private BancoManager bancoManager;
    private SQLiteDatabase sqld;

    public Banco(BancoManager bancoManager) {
        this.bancoManager = bancoManager;
    }

    public void open() {
        sqld = bancoManager.getWritableDatabase();
    }

    public SQLiteDatabase get() {
        if (sqld != null && sqld.isOpen()) {
            return sqld;
        }
        return null;
    }

    public void close() {
        bancoManager.close();
    }
}

Vamos usar a BancoManager.java como explicado anteriormente. Criei o BancoUsuarios.java que irá tratar da criação do nosso banco e atualização.

public class BancoUsuarios extends BancoManager {
    //nome do banco de dados e versão
    public static final String NAME = "dBusuarios";
    public static final String TAG_LOG = "BancoUsuarios";
    public static final int VERSAO = 1;

    public BancoUsuarios(Context context) {
        //defino pelo contrutor do BancoManager a versão e o nome do banco
        super(context, NAME, VERSAO);
    }

    @Override
    public void onCreate(SQLiteDatabase bd) {
        criaTabelas(bd);
    }

    /**
     * Este método é chamado automaticamente quando a versão é alterada.
     */
    @Override
    public void onUpgrade(SQLiteDatabase bd, int versaoAtual, int versaoNova) {
        //realizaa tratamento de upgrade, caso tenha
        //alteração em tabelas por exemplo.
        Log.e(TAG_LOG, "V.atual: " + versaoAtual);
        Log.e(TAG_LOG, "Nova V.: " + versaoNova);
        //Aqui você deve fazer o tratamento do update do banco.
        //no caso estou apagando minha tabela e criando novamente.
        try {
            bd.execSQL("drop table usuarios_tbl;");
        } catch (Exception e) {
            Log.e(TAG_LOG, "onUpgrade", e);
        }
        criaTabelas(bd);
    }

    private void criaTabelas(SQLiteDatabase bd) {
        try {
            //crio o banco de dados atravez do arquivo create.
            byFile(R.raw.create, bd);
        } catch (Exception e) {
            Log.e(TAG_LOG, "criaTabelas", e);
        }
    }
}

Como vimos implementamos tudo que é necessário para a criação e atualização do banco. Caso alguém não saiba a classe Log.java é responsável em escrever no DDMS(aprenda a usar) que é nosso gerenciador de log de eventos, ninguém que programa em android vive sem o DDMS.

Agora que criamos toda nossa estrutura, construímos nosso alicerce, vamos mostrar nossa classe MainActivity.java por partes, definimos a estrutura da seguinte maneira:.

public class MainActivity extends Activity {
    public static final String TAG_LOG = "ExemploBanco";
    private Banco banco;

    @Override
    public void onCreate(Bundle savedInstanceState)...

    private void insert(String usuario)...
    private void select()...
    private void update(String usuario, String novo)...
    private void delete(String usuario)...
}

Temos nossa tag de log e nosso Banco definido anteriormente.
O método onCreate vamos fazer toda chamada, iniciar o banco chamar os métodos etc…

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //inicia e abre banco
        banco = new Banco(new BancoUsuarios(this));
        banco.open();
        //inicia o exemplo (insert,select,update,delete)
        Log.d(TAG_LOG, "nINSERT");
        //insiro o usuario
        insert("gbzarelli");
        //insiro o usuario
        insert("registro_" + System.currentTimeMillis());
        select();//busco

        Log.d(TAG_LOG, "nUPDATE");
        String update = "gbzarelli_" + System.currentTimeMillis();
        //atualizo o nome
        update("gbzarelli", update);
        select();//busco

        Log.d(TAG_LOG, "nDELETE");
        delete(update);//deleto o registro
        select();//busco

        banco.close();//fecha o banco
    }

Acredito que até ai não tenha segredo, estamos inserindo dois usuários, um com o parâmetro “gbzarelli” e o outro “registro_xxxxxx” (esse parâmetro vai ser o usuário), após ter inserido fazemos um update mudando o usuário de “gbzarelli” para “gbzarelli_xxxxxx” e por fim fazemos um delete no usuário que foi alterado. Entre essas operações estamos realizando um select para mostrar as informações.

O Insert – Notamos que utilizamos uma classe chamada ContentValues que serve para linkar a coluna com o registro, essa classe é como se fosse um hashmap. Após o registro ser inserido é retornado um long que é respectivo ao id primário da tabela.

    private void insert(String usuario) {
        //inserir dados
        ContentValues cv = new ContentValues();
        cv.put("usuario", usuario);
        cv.put("senha", "147147");
        cv.put("nome_completo", "Guilherme Biff Zarelli");
        long l = banco.get().insert("usuarios_tbl", null, cv);
        Log.i(TAG_LOG, "id insert: " + l);
    }

O Select - Aqui usamos  uma query comum, realizada na mão e passamos os parâmetros através de um array de string cada posição é respectiva com a ordem dos pontos de interrogação. Vemos também o uso do Cursor que é referente ao ResultSet utilizado no JavaSE.

    private void select() {
        //O cursor no android é similar ao ResultSet do Java
        Cursor cursor = banco.get().rawQuery("select * from usuarios_tbl limit ?", new String[]{"5"});
        while (cursor.moveToNext()) {
            Log.i(TAG_LOG, "id: " + cursor.getInt(cursor.getColumnIndex("id_usuarios")));
            Log.i(TAG_LOG, "usuario: " + cursor.getString(cursor.getColumnIndex("usuario")));
            Log.i(TAG_LOG, "senha: " + cursor.getString(cursor.getColumnIndex("senha")));
            Log.i(TAG_LOG, "nomeCompleto: " + cursor.getString(cursor.getColumnIndex("nome_completo")));
            Log.i(TAG_LOG, "-------");
        }
        //Nunca esqueça de feixar o cursor.
        cursor.close();
    }

O Update – Também utilizamos o ContentValues e o array de parâmetros

    private void update(String usuario, String novo) {
        ContentValues cv = new ContentValues();
        cv.put("usuario", novo);
        banco.get().update("usuarios_tbl", cv, "usuario==?", new String[]{usuario});
    }

O Delete – No delete passamos a tabela e a condição e também o array de parâmetros.

    private void delete(String usuario) {
        banco.get().delete("usuarios_tbl", "usuario==?", new String[]{usuario});
    }

Pronto, na implementação podemos notar que existe várias de maneiras de fazer um select,insert,update ou delete, a classe SQLiteDatabase é bem complexa e cheio de métodos, somente com a prática podemos criar um controle agradável e bem usual. Agora basta estudar e ir aprimorando seu código.

Se rodarmos vamos notar no DDMS mais ou menos o seguinte Log:
Log DDMS banco de dados sqlite3

Caso queiram o projeto segue o link: ProjetoExemploBanco , o projeto foi realizado no NetBeans sobre o Fedora 16 x64 e configurado para a versão 3.2 do Android.

Caso queira usar o NetBeans como sua IDE de Android faça os seguintes procedimentos (AQUI).

Help DEV – Analista desenvolvedor Java / Android

http://helpdev.com.br/zarelli

28 thoughts on “Banco de dados para Android

  1. Pingback: Android – Opções de Armazenamento (persistência de dados) « Think Different – Develop

      • Obrigado pela a resposta , agora eu tenho mais uma duvida , onde fica salvo o arquivo do banco que eu acabei de criar! pois eu necessito testar minhas pesquisas por uma ferramenta CASE chamada SQLite Expert Personal

  2. mto bom o artigo que vc escreveu, porem quand eu tento dah um erro de no such table nao existe a tabela, Tipo tenho 2 activity eu abro o banco na activity de cadastro de cliente. mas ele sempre dah o mesmo erro. se puder dar um help eu agradeceria mtoooo

  3. Oi gilherme desculpe a demora pra resposta. Vi q android funciona um pouco diferente de um apicativo java comum. è mais a questao dos objetos que não vi como que ele seta os atributos do objeto. Pra qua busca eu sempre faça pelos objetos. Como seta os atributos à classe??

    • Caio, o Android funciona igual ao Java porem tem um conceito diferente em relação a interface. Você seta os atributos de uma classe pelos métodos get’s e set’s normalmente identico ao java. O que seria uma classe para você? de qual classe especificamente você se refere ?… esclareça sua pergunta, obrigado.

  4. Pingback: Banco de dados para Android « Arthur Lehdermann

  5. Sou nova com desenvolvimento para Android. Lendo seus posts resolvi criar um aplicativo experimental, só que surgiu uma dúvida
    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??

    • Todas essas perguntas da para responder neste post. O mais importante que você quer saber é como criar um banco de dados com dados já inserido.. seguindo a explicação do post basta você criar o arquivo .sql na pasta raw do projeto. Neste arquivo, basta ter o create do banco e a inserção dos registros como no exemplo abaixo:

      ===========arquivo .sql============
      CREATE TABLE usuarios_tbl (
      id_usuarios INTEGER PRIMARY KEY autoincrement,
      usuario varchar(45) NOT NULL ,
      senha varchar(45) NOT NULL,
      nome_completo varchar(45) NOT NULL
      );

      INSERT INTO usuarios_tbl(id_usuarios, usuario, senha, nome_completo) VALUES(1,”gui”,”123″,”guilherme biff”);
      …[insert]
      …[insert]
      …[insert]
      ==================================

      pronto usando a classe do exemplo, você terá seu banco com registros.

      O resto já parte para um conceito de regra de negocios…
      Para utilizar um Spinner é simples, tendo o array de elementos basta fazer:

      String[] itens = new String[]{“a”,”b”};
      ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, itens);
      spinner.setAdapter(adapter);

      Para descobrir qual item você selecionou no spinner basta implementar o listener de item selecionado:

      spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() {

      public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) {
      adapter.get(arg2);//pronto você tem o item.
      //aqui você pode chamar uma função para carregar os dados do outro spinner.
      }
      });

      Para passar parametros entre telas faça:
      Intent it = new Intent(this,Tela2.class);
      it.putExtra(“dado1″, “valor1″);
      it.putExtra(“dado2″, “valor2″);
      startActivity(it);

      Para capturar esses dados:
      getIntent().getStringExtra(“dado1″);

  6. Pingback: Android – Opções de Armazenamento (persistência de dados) | Help DEV

    • Neste exemplo voce pode gerar um String[] dos resultados do banco, ou até mesmo um objeto com os dados. Para popular um Spinner voce deve fazer um ArrayAdapter:

      ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,resultadosBanco);
      spinner.setAdapter(adapter);

      aonde ‘resultadosBanco’ é um String[] e ‘android.R.layout.simple_list_item_1′ é um item do próprio android. Voce pode definir um item para você, basta criar um xml que contenha um TextView e mudar o parametro para seu layout.

      • gostaria de saber como eu faço um pego uma tabela de um mysql e jogo em uma listview no android sem usar a biblioteca org.apache pois essa biblioteca sempre da problemas
        obrigado

        • O correto seria voce ter um servidor qualquer para buscar as informações, o servidor te retornando os dados sejam eles em XML,Objeto ou outro tipo você trata os dados e popula um Adapter para seu listview. Fazer tudo isso automatico não recomendo, até porque o Android não vai conseguir acessar uma base mysql externa sem passar por um servidor.

  7. O post me ajudou bastante, mas tenho uma dúvida: eu gostaria de ter uma tabela de login com os registros pré-definidos e pelo que me parece, não tenho certeza, o método onCreate() é executado toda vez que o aplicativo é iniciado. Então como faria para criar a tabela Login no banco apenas uma vez?

    Desde já agradeço e parabéns pelo post.

    • Tudo bem Alvaro… é simples, o banco é criado apenas uma vez, caso necessite de uma alteração voce deve incrementar a ‘versão’ e trata-la, então basta adicionar seus insert no arquivo sql do exemplo ficando:

      =======================create.sql===============================
      CREATE TABLE usuarios_tbl (
      id_usuarios INTEGER PRIMARY KEY autoincrement,
      usuario varchar(45) NOT NULL ,
      senha varchar(45) NOT NULL,
      nome_completo varchar(45) NOT NULL
      );

      insert into usuarios_tbl(usuario,senha,nome_completo) values(“gbzarelli”,”123″,”guilherme”);
      ======================================================

  8. criei uma classe para inserir os usuários na tabela. segue o código:

    public class Usuarios
    {

    private Banco banco;
    public static final String TAG_LOG = “ExemploBanco”;

    public void inserir(String nome, String senha, String email) throws Exception {

    banco = new Banco(new BancoRodante(this));

    String senha_c = Criptografa.sha256(senha);

    banco.open();

    ContentValues cv = new ContentValues();
    cv.put(“id_usuario_web”, “1″);
    cv.put(“sincronia”, “0″);
    cv.put(“numero_serie_aparelho”, “0123456789″);
    cv.put(“aparelhos_atualizados”, “1″);
    cv.put(“id_empresa”, “1″);

    cv.put(“nome”, nome+””);
    cv.put(“email”, email+””);
    cv.put(“senha”, senha_c+””);

    cv.put(“data”, “2013/10/17″);
    cv.put(“hora”, “15:25:00″);
    cv.put(“ativo”, “s”);

    long l = banco.get().insert(“usuario”, null, cv);
    Log.i(TAG_LOG, “id insert: ” + l);

    banco.close();

    }
    }

    mas da erro quando tento abrir o banco para poder inserir os dados.
    na linha: banco = new Banco(new BancoRodante(this));
    Será que podes me ajudar.

  9. Ótimo post.

    Gostaria de uma informação e como faze-la, Como faço para que na tela activity no androide só mudar os nome do botão ou text view, sem alterar o layout dando a entender que houvesse várias telas.
    desde já agradeço.

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>