domingo, 26 de fevereiro de 2012

Android - Criando menu

Olá

Hoje vamos aprender como criar um Menu manualmente, como todos devem saber é de grande importância em qualquer aplicativo se ter um menu com as opções que forem necessárias ao aplicativo.

Para isso devemos implementar dois métodos que já são nativos a qualquer Activity.

Abaixo segue o fonte necessário para criar um menu.

Arquivo main.xml, layout da única tela apresentada nesse projeto:
<?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:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="Escola de Android - criando menu"/>
</LinearLayout>


Arquivo main.java:
package br.com.EscolaDeAndroid.Menu;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.Toast;

public class main extends Activity {
    //definição das constantes utilizadas na criação do menu
    private static final int ARQUIVO = 0;
    private static final int EDITAR = 1;
    private static final int FORMATAR = 2;

    private static final int ARQ_NOVO = 3;
    private static final int ARQ_SALVAR = 4;

    private static final int EDITAR_RECORTAR = 5;
    private static final int EDITAR_COPIAR = 6;
    
    private static final int FORMATAR_FONTE = 7;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    //o método abaixo é disparado quando o usuário
    //clicar no botão "Menu" do aparelho
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        try
        {
            //cria o menu e submenus
            SubMenu menuArquivo = menu.addSubMenu(ARQUIVO, 0, 0, "Arquivo");
            SubMenu menuEditar = menu.addSubMenu(EDITAR, 1, 0, "Editar");
            MenuItem menuFormatar = menu.add(FORMATAR, FORMATAR_FONTE, 0, "Formatar");        
            
            //define uma tecla de atalho para o menu, nesse caso a 
            //tecla de atalho é a letra "F"
            menuFormatar.setShortcut('0', 'F');
            
            //adiciona um ícone ao menu
            //menuFormatar.setIcon(R.drawable.icon);
            menuFormatar.setIcon(android.R.drawable.ic_menu_edit);
            
            //caso seja necessário desabilitar o menu Arquivo
            //abaixo segue exemplo
            //menu.findItem(ARQUIVO).setEnabled(false);
    
            menuArquivo.add(ARQUIVO, ARQ_NOVO, 0, "Novo");
            menuArquivo.add(ARQUIVO, ARQ_SALVAR, 1, "Salvar");
            menuArquivo.setIcon(android.R.drawable.ic_menu_more);
            
            //caso seja necessário desabilitar um subitem do menu Arquivo
            //abaixo segue exemplo
            //menuArquivo.findItem(ARQ_NOVO).setEnabled(false);
            
            menuEditar.add(EDITAR, EDITAR_RECORTAR, 0, "Recortar");
            menuEditar.add(EDITAR, EDITAR_COPIAR, 1, "Copiar");
    
            //caso seja necessário desabilitar um subitem do menu Editar
            //abaixo segue exemplo
            //menuEditar.findItem(EDITAR_COPIAR).setEnabled(false);
        }
        catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }            
        return super.onCreateOptionsMenu(menu);        
    }

    //o método abaixo é disparado quando o usuário clicar 
    //em algum dos itens do menu
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //de acordo com o item selecionado você executará
        //a função desejada
        switch (item.getItemId()) {
            case ARQ_NOVO:     
                trace("Você selecionou o menu Novo");
                break;
            case ARQ_SALVAR:     
                trace("Você selecionou o menu Salvar");
                break;
            case EDITAR_COPIAR: 
                trace("Você selecionou o menu Copiar");
                break;
            case EDITAR_RECORTAR: 
                trace("Você selecionou o menu Recortar");
                break;
            case FORMATAR_FONTE: 
                trace("Você selecionou o menu Formatar");
                break;
        }
        return true;
    }    
    
    private void trace (String msg) 
    {
        Toast.makeText (getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
    }
    
}


Neste exemplo utilizado temos as seguintes opções:
1. menu simples
2. menu com submenu
3. habilitar e desabilitar itens do menu
4. inserir imagens
5. parametrizar tecla de atalho

Como resultado temos as imagens abaixo:
Clicando no botão Menu de seu aparelho será apresentado o Menu raiz, se clicar no item "Arquivo", será exibido um submenu com as opções "Novo" e "Salvar", se clicar na opção "Novo", será exibido a mensagem que você clicou no Menu "Novo".
 
































Espero que seja útil para você este tutorial.



Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.


Desenv com qualidade!

quinta-feira, 23 de fevereiro de 2012

Android - ProgressDialog

Olá,

Hoje irei mostrar como utilizar a classe ProgressDialog, ela é de grande utilidade em nosso sistemas, principalmente quando o sistema precisa efetuar alguma operação mais demorada e não deixar o usuário com aquela sensação de que o sistema travou.

Existem dois tipos de ProgressDialog que podem ser utilizados:
1 - Loop infinito - Quando você não consegue precisar quando a operação vai terminar, exemplo uma consulta a base de dados que seja muito demorada
2 - Loop finito - Quando por exemplo, você sabe exatamente a quantidade de registros que o seu sistema irá processar.

Como já de costume todos os fontes abaixo estão com vários comentários para facilitar o aprendizado.

Arquivo main.xml, layout da única tela apresentada nesse projeto:
<?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"
    >

    <Button 
        android:text="Progress 1" 
        android:id="@+id/button1" 
        android:onClick="Progress1_Click"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content">
    </Button>
    <Button 
        android:text="Progress 2" 
        android:id="@+id/button2" 
        android:onClick="Progress2_Click"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content">
    </Button>
</LinearLayout>

Arquivo main.java:
package br.com.EscaloDeAndroid.Progress;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class main extends Activity {
    
    private ProgressDialog mprogressDialog;
    private Handler mhandler;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mhandler = new Handler();
    }
    
    //o botão abaixo irá simular um processo em que não sabemos quanto tempo
    //ele irá demorar
    public void Progress1_Click(View v)
    {
        //cria o progress dialog
        mprogressDialog = ProgressDialog.show(main.this, "Aguarde", "Processando...");

        
        new Thread() {
            public void run() {
                //criando instância de classe para executar um método qualquer
                teste lteste = new teste();
                try{
                    //esse é apenas um método de teste que pode ser demorado
                    lteste.Esperar(10); 
                } catch (Exception e) {
                    Log.e("tag", e.getMessage());
                }
                //encerra progress dialog
                mprogressDialog.dismiss();
            }
        }.start();
    }
    
    //o botão abaixo irá simular uma barra com progressão
    //e poderemos monitorar seu progresso
    public void Progress2_Click(View v)
    {
        mprogressDialog = new ProgressDialog(this);
        mprogressDialog.setCancelable(true);
        mprogressDialog.setMessage("Processando...");

        //define o estilo como horizontal que nesse caso signifca que terá 
        //barra de progressão/contagem
        mprogressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

        //reseta o progress para zero e em seguida define o valor máximo
        mprogressDialog.setProgress(0);
        mprogressDialog.setMax(8); //esse valor deverá ser definido de acordo com sua necessidade

        //apresnta o progressbar
        mprogressDialog.show();
        
        new Thread() {
            public void run() {
                //criando instância de classe para executar um método qualquer
                teste lteste = new teste();
                try{
                    while (mprogressDialog.getProgress() < mprogressDialog.getMax()) {
                        //esse é apenas um método de teste que pode ser demorado
                        lteste.Esperar(1);
                        mprogressDialog.incrementProgressBy(1);
                    }
                } catch (Exception e) {
                    Log.e("tag", e.getMessage());
                }
                
                //Exibe mensagem apenas informando o fim da execução da thread
                mhandler.post(new Runnable() {
                    public void run() {
                        Toast.makeText(getApplicationContext(), "Acabou", Toast.LENGTH_LONG).show();
                    }
                });            
                
                //encerra progress dialog
                mprogressDialog.dismiss();
            }
        }.start();
    }
}


Abaixo segue o arquivo teste.java:
package br.com.EscaloDeAndroid.Progress;

public class teste extends Thread {
    public void Esperar(int pintSegundos)
    {
        try {
            //simulando um processo demorado
            Thread.sleep(pintSegundos * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


Como resultado temos as seguintes imagens:
 


Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.


Desenv com qualidade!

quinta-feira, 9 de fevereiro de 2012

Android - Trabalhando com arquivo texto Parte 1

Olá

Hoje iremos começar mais uma série de artigos e estes agora serão voltados a manipulação de arquivos, nesse projeto serão criadas  três rotinas que são:
1º - criação de arquivos
2º - leitura de arquivos
3º - obter o System Root (diretório de armazenamento externo do Android)

Um detalhe importante para esse projeto é que será necessário habilitar a permissão WRITE_EXTERNAL_STORAGE no arquivo de manifest, é graças a essa permissão que seu aplicativo pode gravar arquivos no SD Card.

Como já de costume todos os fontes abaixo estão com vários comentários para facilitar o aprendizado.


Arquivo main.xml, layout da única tela apresentada nesse projeto:
<?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:text="Root:" 
        android:id="@+id/txtRoot2" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>
    
    <TextView 
        android:text="Nome do arquivo:" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>
        
    <EditText 
        android:id="@+id/edtNomeArq" 
        android:text="teste.txt" 
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>

    <TextView 
        android:text="Texto do arquivo a ser salvo:" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>
        
    <EditText 
        android:id="@+id/edtSalvar" 
        android:text="Escrever arquivo" 
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>

    <TextView 
        android:text="Arquivo lido:" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"/>

    <EditText 
        android:id="@+id/edtLer" 
        android:text=""
        android:layout_height="wrap_content" 
        android:layout_width="fill_parent"/>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">
        <Button
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content" 
            android:onClick="click_Salvar"
            android:text="Salvar" />
        <Button
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content"
            android:onClick="click_Ler" 
            android:text="Abrir" />
        <Button
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content"
            android:onClick="click_Limpar" 
            android:text="Limpar" />
    </LinearLayout>
</LinearLayout>

Arquivo AndroidManifest.xml, contém configurações iniciais do aplicativo:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="br.com.EscolaDeAndroid.ArquivoTexto"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    
</manifest>


Arquivo main.java, classe que contém todo o fonte necessário para este projeto:
package br.com.EscolaDeAndroid.ArquivoTexto;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class main extends Activity {
    private TextView txtRoot;
    private TextView txtNomeArq;
    private TextView txtSalvar;
    private TextView txtLer;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            setContentView(R.layout.main);

            txtRoot = (TextView) findViewById(R.id.txtRoot2);
            txtNomeArq = (TextView) findViewById(R.id.edtNomeArq);
            txtSalvar = (TextView) findViewById(R.id.edtSalvar);
            txtLer = (TextView) findViewById(R.id.edtLer);
        
        
            txtRoot.append(GetRoot());        
        
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }
    
    public void click_Salvar(View v)
    {
        SalvarArquivo();
    }

    public void click_Ler(View v)
    {
        LerArquivo();
    }

    public void click_Limpar(View v)
    {
        txtNomeArq.setText("teste.txt");
        txtSalvar.setText("");
        txtLer.setText("");
    }
    
    //Exibir o diretório de armazenamento externo do Android
    private String GetRoot()
    {
        File root = android.os.Environment.getExternalStorageDirectory(); 
        return root.toString();
    }
    
    private void SalvarArquivo()
    {
        String lstrNomeArq;
        File arq;
        byte[] dados;
        try
        {
            //pega o nome do arquivo a ser gravado
            lstrNomeArq = txtNomeArq.getText().toString();
            
            arq = new File(Environment.getExternalStorageDirectory(), lstrNomeArq);
            FileOutputStream fos;
            
            //transforma o texto digitado em array de bytes
            dados = txtSalvar.getText().toString().getBytes();
            
            fos = new FileOutputStream(arq);
            
            //escreve os dados e fecha o arquivo
            fos.write(dados);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }

    private void LerArquivo()
    {
        String lstrNomeArq;
        File arq; 
        String lstrlinha;
        try
        {
            //pega o nome do arquivo a ser lido
            lstrNomeArq = txtNomeArq.getText().toString();

            //limpa a caixa de texto que irá receber os dados do arquivo
            txtLer.setText("");

            
            arq = new File(Environment.getExternalStorageDirectory(), lstrNomeArq);
            BufferedReader br = new BufferedReader(new FileReader(arq));
            //efetua uma leitura linha a linha do arquivo a carrega 
            //a caixa de texto com a informação lida
            while ((lstrlinha = br.readLine()) != null) {
                if (!txtLer.getText().toString().equals(""))
                {
                    txtLer.append("\n");
                }
                txtLer.append(lstrlinha);
            }            
            
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }

    public void toast (String msg)
    {
        Toast.makeText (getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
    } 
    
    private void trace (String msg) 
    {
        toast (msg);
    }    
}

Abaixo temos o resultado prático de nosso projeto:


O funcionamento do projeto será o seguinte:
1º - na primeira caixa de texto será o local onde o usuário irá informar o nome do arquivo a ser salvo, por padrão o nome do arquivo será teste.txt, mas o usuário poderá informar o nome que desejar.
2º - na segunda caixa de texto será para digitar o conteúdo de nosso arquivo, em seguida o usuário deve clicar no botão "Salvar" para efetuar a gravação do arquivo.
3º - clicando no botão "Abrir" o sistema irá buscar o arquivo de acordo com a primeira caixa de texto e exibir o conteúdo na terceira caixa de texto.
4º - clicando no botão "Limpar" o aplicativo limpará a segunda e a terceira caixa de texto.

Obs.: não fiz tratamento de erro do tipo, arquivo não encontrado, se deseja substituir o arquivo já existente, esses serão temas para os próximos artigos.



Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.


Desenv com qualidade!

segunda-feira, 6 de fevereiro de 2012

Android - Gerando gráficos com Google Chart API

Olá,


Atualmente todo aplicativo comercial que se preze necessita exibir dados em formas de gráficos e hoje vou mostrar como desenvolver gráficos para Android utilizando a Api Google Chart, a princípio é muito fácil, para isto basta utilizar um controle WebView e habilitar a permissão para utilização de INTERNET.

No projeto apresentado abaixo os dados do gráfico estão fixos no fonte, cabe a você montar em seu aplicativo uma string dinâmica com dados reais e passar como URL no método loadUrl do componente WebView, abaixo seguem todos os fontes utilizados no sistema.


Arquivo main.xml, layout da única tela apresentada nesse projeto:
<?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"
    >

    <WebView
        android:id="@+id/wvGrafico"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"/>    
</LinearLayout>

Arquivo AndroidManifest.xml, contém configurações iniciais do aplicativo:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="br.com.EscoladeAndroid.Grafico"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    <activity android:name="org.achartengine.GraphicalActivity"/> 

    </application>
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>    
</manifest>

Arquivo main.java, classe que irá exibir o gráfico:
package br.com.EscoladeAndroid.Grafico;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Toast;

public class main extends Activity {
    WebView wvGrafico;
    String strURL;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        strURL = "https://chart.googleapis.com/chart?" + 
            "cht=lc&" + //define o tipo do gráfico "linha"
            "chxt=x,y&" + //imprime os valores dos eixos X, Y
            "chs=300x300&" + //define o tamanho da imagem
            "chd=t:10,45,5,10,13,26&" + //valor de cada coluna do gráfico
            "chl=Jan|Fev|Mar|Abr|Mai|Jun&" + //rótulo para cada coluna
            "chdl=Vendas&" + //legenda do gráfico
            "chxr=1,0,50&" + //define o valor de início e fim do eixo 
            "chds=0,50&" + //define o valor de escala dos dados 
            "chg=0,5,0,0&" + //desenha linha horizontal na grade
            "chco=3D7930&" + //cor da linha do gráfico 
            "chtt=Vendas+x+1000&" + //cabeçalho do gráfico
            "chm=B,C5D4B5BB,0,0,0"; //fundo verde 

        
        //Abaixo seguem outros exemplo de gráfico:
        //strURL = "https://chart.googleapis.com/chart?cht=lc&chxt=x,y&chs=300x300&chd=t:10,45,5,10,13,26&chl=Janeiro|Fevereiro|Marco|Abril|Maio|Junho&chdl=Vendas%20&chxr=1,0,50&chds=0,25&chg=0,5,0,0&chco=3D7930&chtt=Vendas+x+1000&chm=v,FF0000,0,::.10,4";
        //strURL = "http://chart.apis.google.com/chart?cht=bhg&chs=550x400&chd=t:100,50,115,80|10,20,15,30&chxt=x,y&chxl=1:|Janeiro|Fevereiro|Marco|Abril&chxr=0,0,120&chds=0,120&chco=4D89F9&chbh=35,0,15&chg=8.33,0,5,0&chco=0A8C8A,EBB671&chdl=Vendas|Compras";
        //strURL = "https://chart.googleapis.com/chart?cht=lc&chxt=x,y&chs=700x350&chd=t:10,45,5,10|30,35,30,15|10,10.5,30,35&chl=Janeiro|Fevereiro|Marco|Abril&chdl=Vendas|Compras|Outros&chxr=1,0,50&chds=0,50&chg=0,5,0,0&chco=DA3B15,3072F3,000000&chtt=grafico+de+vendas";
        //strURL = "https://chart.googleapis.com/chart?cht=p3&chs=200x90&chd=t:40,45,5,10&chl=Jan|Fev|Mar|Abr";
        //strURL = "http://chart.apis.google.com/chart?chxl=0:|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec&chxt=x,y&chs=300x300&cht=r&chco=FF0000&chd=t:63,64,67,73,77,81,85,86,85,81,74,67,63&chls=2,4,0&chm=B,FF000080,0,0,0";

        wvGrafico = (WebView)findViewById(R.id.wvGrafico);
        wvGrafico.loadUrl(strURL);
        
    }
}

Ao executar esse aplicativo teremos a seguinte imagem:


Agora vamos ver uma pequena explicação sobre cada um dos principais atributos de nosso gráfico:


Chart Type (cht) : tipo de gráfico que será utilizado (pizza (p, p3, pc), barra (bhs, bvs, bhg, bvg, bvo), linha (lc, ls, lxy))

Chart Size (chs) : define o tamanho em pixels para seu gráfico (width x height)

Chart Data (chd) : dados que você irá apresentar em seu gráfico

Chart Colour (chco) : cor ou cores que serão utilizados em seu gráfico deve-se utilizar a representação Hex (RRGGBB)

Chart Labels (chl) : define os rótulos que seu gráfico terá, normalmente você irá utilizar um rótulo para cada Dado utilizados em (chd)

Chart Grid Lines (chg) : desenha linhas dentro de seu gráfico para facilitar e leitura de cada gráfico, esse atributo possui 4 parâmetros que são chg = <verticalGridLines>, <horizontalGridLines>, <lineSize>, <gapSize>

Char Title (chtt) : define o título do gráfico

Chart Legend (chdl) : define a legenda do gráfico, normalmente será definida por uma barra lateral vertical

Chart Data Scale (chds) : define os valores de mínimo e máximo para o gráfico, qualquer valor maior que o máximo será exibido como se fosse o máximo.

Char Axis Range (chxr) : determina de início e fim do eixo, esse atributo possui três parâmetros, o primeiro determina qual eixo está sendo utilizado, o segundo e o terceiro definem a própria faixa de atuação do gráfico

Chart Shape Markers (chm) : Preenche o conteúdo do gráfico com uma cor definida, exemplo: (chm=B,C5D4B5BB,0,0,0) ou (chm=v,FF0000,0,::.10,4)

Char Visible Axis (chxt) : mostra os números dos eixos X,Y



Referência:
http://code.google.com/intl/pt-BR/apis/chart/image/docs/gallery/chart_gall.html


Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.


Desenv com qualidade!

sábado, 4 de fevereiro de 2012

Ganhar dinheiro com Android - Parte 3

Olá

Mais uma vez estou aqui escrevendo sobre como ganhar dinheiro com Android, bem..., consegui receber meu primeiro pagamento referente meu jogo Circus Puzzle Free o pagamento saiu agora em Janeiro de 2012, depois de  6 meses com o aplicativo publicado no Google Market, ele me rendeu US$24,96 até o dia 12/01/2012.

Pretendo em breve criar uma segunda versão do mesmo jogo, só que desta pago e sem propaganda para ver se o retorno é maior, assim que possível eu posto mais novidades sobre esse assunto.

Agora explicando como foi que recebi meu pagamento, eu acompanho todos os dias o site do AdMob para ver quanto cliques são realizados em meu aplicativo e um dia vi que o AdMob tinha liberado um pagamento para mim, em seguida criei uma conta no PayPal e depois eu a vinculei com a minha conta do AdMob depois disso foi só esperar uns dois ou três dias úteis e meu pagamento caiu na minha conta bancaria.

Abaixo segue uma imagem do PayPal sobre a liberação do pagamento.


Sei que o valor é baixo, mas nem por isso me desanimo, oque eu queria era conhecer todo o fluxo desde o desenvolvimento, publicação, propaganda e recebimento e consegui verificar que ele funciona.

Por enquanto é isso.

Parte 1 : http://escoladeandroid.blogspot.com/2011/08/ganhar-dinheiro-com-android.html
Parte 2 : http://escoladeandroid.blogspot.com/2011/11/ganhar-dinheiro-com-android-parte-2.html



Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.



Desenv com qualidade!

Android - Criando uma Agenda de Contatos com SQLite

Olá,

Hoje apresentarei para vocês como trabalhar com o Banco de Dados SQLite, serão apresentadas as operações básicas de um banco de dados (inclusão, exclusão, alteração e consulta) o projeto é uma Agenda de Contatos e ele está separado em camadas e cada camada está dentro de uma package, abaixo seguem as camadas utilizadas:

Camadas:
1. UI - User Interface, responsável pela interação entre o usuário e o sistema.
2. POJO - Plain Old Java Objects, responsável pelo transporte dos dados entre o BD, regras de negócio e o usuário.
2. DAO - Data Access Object, responsável pela persistência dos dados.

Abaixo segue uma figura com a estrutura e todos os arquivos que criaremos nesse projeto:


Além das camadas o projeto também utiliza um Adapter customizado (ContatoAdapter), para poder apresentar mais de uma linha de informação para cada item de nossa ListView, pois na mesma tela presentaremos todos os contatos cadastrados.

Abaixo vou apresentar todos os fontes e xml criados nesse projeto, todos os fontes estarão com vários comentários para auxiliar no bom entendimento do projeto.

Iremos começar pelos arquivos xml:

Arquivo arrays.xml, contém os itens que serão apresentados no ContextMenu:
<?xml version="1.0" encoding="utf-8"?>
<resources>    
    <string-array name="menu">        
        <item>Editar</item>        
        <item>Excluir</item>        
    </string-array>        
</resources>


Arquivo main.xml, layout da tela de consulta dos Contatos:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
        <Button
            android:id="@+id/add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Adicionar" 
            android:onClick="onClick"/>
    </LinearLayout>

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
</LinearLayout>

Layout gráfico do main.xml


Arquivo contato.xml, layout da tela de inclusão e alteração do Contato:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
    <TextView 
        android:id="@+id/txtAux1" 
        android:text="Nome :"
        android:gravity="right"
        android:width="70dip" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content"
        android:layout_marginTop="10dip"
        >
    </TextView>
    <EditText 
        android:id="@+id/edtNome" 
        android:layout_marginLeft="5dip"
        android:text="Nome contato" 
        android:width="190dip"
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content"
        android:layout_toRightOf="@+id/txtAux1">
    </EditText>
    <TextView 
        android:id="@+id/txtAux3" 
        android:text="Endereço :" 
        android:width="70dip"
        android:gravity="right"
        android:layout_marginTop="10dip"
        android:layout_centerVertical="@+id/txtAux2" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content" 
        android:layout_below="@+id/edtNome"
        android:layout_alignParentLeft="true">
    </TextView>
    <EditText 
        android:id="@+id/edtEndereco" 
        android:layout_marginLeft="5dip"
        android:text="Endereco contato"
        android:width="190dip" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content"
        android:layout_below="@+id/edtNome" 
        android:layout_toRightOf="@+id/txtAux3">
    </EditText>
    <TextView 
        android:id="@+id/txtAux5" 
        android:text="Telefone :" 
        android:width="70dip"
        android:gravity="right"
        android:layout_marginTop="10dip"
        android:layout_centerVertical="@+id/txtAux2" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content" 
        android:layout_below="@+id/edtEndereco"
        android:layout_alignParentLeft="true">
    </TextView>
    <EditText 
        android:id="@+id/edtTelefone" 
        android:layout_marginLeft="5dip"
        android:text="Telefone contato"
        android:width="190dip" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content"
        android:layout_below="@+id/edtEndereco" 
        android:layout_toRightOf="@+id/txtAux5">
    </EditText>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/edtTelefone" 
        android:gravity="center_vertical">    
        <Button 
            android:text="Confirmar" 
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:layout_height="wrap_content" 
            android:id="@+id/btnConfirmar"
            android:layout_below="@+id/edtTelefone" 
            android:onClick="btnConfirmar_click"
            android:layout_alignParentLeft="true">
        </Button>

        <Button 
            android:text="Cancelar" 
            android:layout_height="wrap_content"
            android:layout_width="0dip"
            android:layout_weight="1.0"
            android:id="@+id/btnCancelar"
            android:layout_below="@+id/edtTelefone" 
            android:onClick="btnCancelar_click"
            android:layout_alignParentRight="true">
        </Button>
    </LinearLayout>
    
</RelativeLayout>

Layout gráfico do contato.xml


Arquivo contato_row.xml, layout de item do ListView utilizado no ContatoAdapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/LinearLayout01"
    android:layout_width="fill_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:orientation="vertical">
       <RelativeLayout 
           android:id="@+id/LinearLayout02"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
            
        <TextView 
            android:layout_height="wrap_content"
            android:layout_width="fill_parent" 
            android:id="@+id/txtNome"
            android:text="Nome">
        </TextView>
        <TextView 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent"
            android:id="@+id/txtEndereco"
            android:text="Endereço"
            android:layout_below="@+id/txtNome">
        </TextView>
        <TextView 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent"
            android:id="@+id/txtTelefone"
            android:text="Telefone"
            android:layout_below="@+id/txtEndereco">
        </TextView>
    </RelativeLayout>
</LinearLayout>

Layout gráfico do contato_row.xml:


Arquivo AndroidManifest.xml, arquivo de configuração utilizado pelo Android:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="br.com.Agenda.UI"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ContatoUI" android:label="@string/app_name"/>

    </application>
</manifest>

Agora irei apresentar as classes que esse projeto irá utilizar.

Arquivo main.java, primeiro classe a ser executada no projeto:
package br.com.Agenda.UI;

import java.util.List;

import br.com.Agenda.DAO.ContatoAdapter;
import br.com.Agenda.DAO.ContatoDAO;
import br.com.Agenda.POJO.ContatoVO;

import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

public class main extends ListActivity{
    private static final int INCLUIR = 0;
    private static final int ALTERAR = 1;
 
    private ContatoDAO lContaoDAO; //instância responsável pela persistência dos dados
    List<ContatoVO> lstContatos;  //lista de contatos cadastrados no BD
    ContatoAdapter adapter;   //Adapter responsável por apresentar os contatos na tela
 
    boolean blnShort = false;
    int Posicao = 0;    //determinar a posição do contato dentro da lista lstContatos

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        lContaoDAO = new ContatoDAO(this);
        lContaoDAO.open();

        lstContatos = lContaoDAO.Consultar();

        adapter = new ContatoAdapter(this, lstContatos);
        setListAdapter(adapter);
  
        registerForContextMenu(getListView());
    }
 
    // Este evento será chamado pelo atributo onClick
    // que está definido no botão criado no arquivo main.xml
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.add:
            InserirContato();
            break;
        }
    }

    //Rotina executada quando finalizar a Activity ContatoUI
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        ContatoVO lAgendaVO = null;
        
        try
        {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == Activity.RESULT_OK)
            {
                //obtem dados inseridos/alterados na Activity ContatoUI
                lAgendaVO = (ContatoVO)data.getExtras().getSerializable("agenda");
                
                //o valor do requestCode foi definido na função startActivityForResult
                if (requestCode == INCLUIR)
                {
                    //verifica se digitou algo no nome do contato
                    if (!lAgendaVO.getNome().equals("")) 
                    {
                        //necessário abrir novamente o BD pois ele foi fechado no método onPause()
                        lContaoDAO.open();
                        
                        //insere o contato no Banco de Dados SQLite
                        lContaoDAO.Inserir(lAgendaVO);
                        
                        //insere o contato na lista de contatos em memória
                        lstContatos.add(lAgendaVO);
                    }
                }else if (requestCode == ALTERAR){
                    lContaoDAO.open();
                    //atualiza o contato no Banco de Dados SQLite
                    lContaoDAO.Alterar(lAgendaVO);
                    
                    //atualiza o contato na lista de contatos em memória
                    lstContatos.set(Posicao, lAgendaVO);
                }
                
                //método responsável pela atualiza da lista de dados na tela
                adapter.notifyDataSetChanged();
            }
        }
        catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }        
    }    
    
    private void InserirContato(){
        try
        {
            //a variável "tipo" tem a função de definir o comportamento da Activity
            //ContatoUI, agora a variável tipo está definida com o valor "0" para
            //informar que será uma inclusão de Contato
            
            Intent it = new Intent(this, ContatoUI.class);
            it.putExtra("tipo", INCLUIR);
            startActivityForResult(it, INCLUIR);//chama a tela e incusão
        }
        catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }            
    }    
    
    @Override
    protected void onResume() {
        //quando a Activity main receber o foco novamente abre-se novamente a conexão
        lContaoDAO.open();
        super.onResume();
    }

    @Override
    protected void onPause() {
        //toda vez que o programa peder o foco fecha-se a conexão com o BD
        lContaoDAO.close();
        super.onPause();
    }

    public void toast (String msg)
    {
        Toast.makeText (getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
    } 
    
    private void trace (String msg) 
    {
        toast (msg);
    }

    @Override    
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {        
        try
        {
            //Criação do popup menu com as opções que termos sobre
            //nossos Contatos
            
            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
            if (!blnShort)
            {
                Posicao = info.position;
            }
            blnShort = false;
            
            menu.setHeaderTitle("Selecione:");            
            //a origem dos dados do menu está definido no arquivo arrays.xml 
            String[] menuItems = getResources().getStringArray(R.array.menu);             
            for (int i = 0; i<menuItems.length; i++) {                
                menu.add(Menu.NONE, i, i, menuItems[i]);            
            }        
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }            
    }  

    
    //Este método é disparado quando o usuário clicar em um item do ContextMenu
    @Override    
    public boolean onContextItemSelected(MenuItem item) {       
        ContatoVO lAgendaVO = null;
        try
        {
            int menuItemIndex = item.getItemId();        

            //Carregar a instância POJO com a posição selecionada na tela
            lAgendaVO = (ContatoVO) getListAdapter().getItem(Posicao);
            
            if (menuItemIndex == 0){
                //Carregar a Activity ContatoUI com o registro selecionado na tela
                
                Intent it = new Intent(this, ContatoUI.class);
                it.putExtra("tipo", ALTERAR);
                it.putExtra("agenda", lAgendaVO);
                startActivityForResult(it, ALTERAR); //chama a tela de alteração
            }else if (menuItemIndex == 1){
                //Excluir do Banco de Dados e da tela o registro selecionado
                
                lContaoDAO.Excluir(lAgendaVO);
                lstContatos.remove(lAgendaVO);
                adapter.notifyDataSetChanged(); //atualiza a tela
            }
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }   
        return true;   
        
    }    

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        //por padrão o ContextMenu, só é executado através de LongClick, mas
        //nesse caso toda vez que executar um ShortClick, abriremos o menu
        //e também guardaremos qual a posição do itm selecionado
        
        Posicao = position;
        blnShort = true;
        this.openContextMenu(l);
    }
}

Arquivo ContaoUI.java, classe que irá controlar a tela de cadastro de contato:
package br.com.Agenda.UI;

import br.com.Agenda.POJO.ContatoVO;
import br.com.Agenda.UI.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class ContatoUI extends Activity {
    private static final int INCLUIR = 0;
    //private static final int ALTERAR = 1;
    ContatoVO lContatoVO; 
    EditText txtNome;
    EditText txtEndereco;
    EditText txtTelefone;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contato);
        
        try
        {
            
        
            final Bundle data = (Bundle) getIntent().getExtras();
            int lint = data.getInt("tipo");
            if (lint == INCLUIR)
            {
                //quando for incluir um contato criamos uma nova instância
                lContatoVO = new ContatoVO(); 
            }else{
                //quando for alterar o contato carregamos a classe que veio por Bundle
                lContatoVO = (ContatoVO)data.getSerializable("agenda");
            }
            
            //Criação dos objetos da Activity
            txtNome = (EditText)findViewById(R.id.edtNome);
            txtEndereco = (EditText)findViewById(R.id.edtEndereco);
            txtTelefone = (EditText)findViewById(R.id.edtTelefone);
    
            //Carregando os objetos com os dados do Contato
            //caso seja uma inclusão ele virá carregado com os atributos text
            //definido no arquivo main.xml
            txtNome.setText(lContatoVO.getNome());
            txtEndereco.setText(lContatoVO.getEndereco());
            txtTelefone.setText(lContatoVO.getTelefone());
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }             
    }

    public void btnConfirmar_click(View view)
    {
        try
        {
            //Quando confirmar a inclusão ou alteração deve-se devolver
            //o registro com os dados preenchidos na tela e informar
            //o RESULT_OK e em seguida finalizar a Activity
            
            
            Intent data = new Intent();
            lContatoVO.setNome(txtNome.getText().toString());
            lContatoVO.setEndereco(txtEndereco.getText().toString());
            lContatoVO.setTelefone(txtTelefone.getText().toString());
            data.putExtra("agenda", lContatoVO);
            setResult(Activity.RESULT_OK, data);    
            finish();
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }             
    }
    
    public void btnCancelar_click(View view)
    {
        try
        {
            //Quando for simplesmente cancelar a operação de inclusão
            //ou alteração deve-se apenas informar o RESULT_CANCELED
            //e em seguida finalizar a Activity
            
            setResult(Activity.RESULT_CANCELED);
            finish();
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }             
    }

    public void toast (String msg)
    {
        Toast.makeText (getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
    } 
    
    private void trace (String msg) 
    {
        toast (msg);
    }    

}


Arquivo ContatoVO.java, será a classe responsável pelo transporte dos dados do Contato entre o usuário e o Banco de Dados SQLite:
package br.com.Agenda.POJO;

import java.io.Serializable;

//Classe responsável pelo transporte dos dados entre a 
//interface(tela) e Banco de Dados
public class ContatoVO implements Serializable {
    private static final long serialVersionUID = 1L;
    private long id;
    private String nome;
    private String endereco;
    private String telefone;

    public long getId() {
        return id;
    }

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

    public String getNome() {
        return nome;
    }

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

    public String getEndereco() {
        return endereco;
    }

    public void setEndereco(String value) {
        this.endereco = value;
    }
    
    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String value) {
        this.telefone = value;
    }
    // Will be used by the ArrayAdapter in the ListView
    @Override
    public String toString() {
        return nome;
    }
}


Arquivo BaseDAO.java, representará o DBHelper, responsável pela criação do próprio Banco de Dados:
package br.com.Agenda.DAO;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

//Classe responsável pela criação do Banco de Dados e tabelas
public class BaseDAO extends SQLiteOpenHelper {

    public static final String TBL_AGENDA = "agenda";
    public static final String AGENDA_ID = "_id";
    public static final String AGENDA_NOME = "nome";
    public static final String AGENDA_ENDERECO = "endereco";
    public static final String AGENDA_TELEFONE = "telefone";

    private static final String DATABASE_NAME = "agenda.db";
    private static final int DATABASE_VERSION = 1;

    //Estrutura da tabela Agenda (sql statement)
    private static final String CREATE_AGENDA = "create table " +
        TBL_AGENDA + "( " + AGENDA_ID       + " integer primary key autoincrement, " + 
                            AGENDA_NOME     + " text not null, " +
                            AGENDA_ENDERECO + " text not null, " +
                            AGENDA_TELEFONE + " text not null);";

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

    @Override
    public void onCreate(SQLiteDatabase database) {
        //Criação da tabela
        database.execSQL(CREATE_AGENDA);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //Caso seja necessário mudar a estrutura da tabela
        //deverá primeiro excluir a tabela e depois recriá-la
        db.execSQL("DROP TABLE IF EXISTS " + TBL_AGENDA);
        onCreate(db);
    }

}


Arquivo ContatoDAO.java, responsável pela persistência dos dados do Contato no Banc de Dados:
package br.com.Agenda.DAO;

import java.util.ArrayList;
import java.util.List;

import br.com.Agenda.POJO.ContatoVO;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

public class ContatoDAO {

    private SQLiteDatabase database;
    private BaseDAO dbHelper;

    //Campos da tabela Agenda
    private String[] colunas = {BaseDAO.AGENDA_ID, 
                                BaseDAO.AGENDA_NOME,
                                BaseDAO.AGENDA_ENDERECO, 
                                BaseDAO.AGENDA_TELEFONE };

    public ContatoDAO(Context context) {
        dbHelper = new BaseDAO(context);
    }

    public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }

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

    public long Inserir(ContatoVO pValue) {
        ContentValues values = new ContentValues();

        //Carregar os valores nos campos do Contato que será incluído
        values.put(BaseDAO.AGENDA_NOME, pValue.getNome());
        values.put(BaseDAO.AGENDA_ENDERECO, pValue.getEndereco());
        values.put(BaseDAO.AGENDA_TELEFONE, pValue.getTelefone());
        
        return database.insert(BaseDAO.TBL_AGENDA, null, values);
    }
    
    
    public int Alterar(ContatoVO pValue) {
        long id = pValue.getId();
        ContentValues values = new ContentValues();
        
        //Carregar os novos valores nos campos que serão alterados
        values.put(BaseDAO.AGENDA_NOME, pValue.getNome());
        values.put(BaseDAO.AGENDA_ENDERECO, pValue.getEndereco());
        values.put(BaseDAO.AGENDA_TELEFONE, pValue.getTelefone());

        //Alterar o registro com base no ID
        return database.update(BaseDAO.TBL_AGENDA, values, BaseDAO.AGENDA_ID + " = " + id, null);
    }

    public void Excluir(ContatoVO pValue) {
        long id = pValue.getId();
        
        //Exclui o registro com base no ID
        database.delete(BaseDAO.TBL_AGENDA, BaseDAO.AGENDA_ID + " = " + id, null);
    }

    public List<ContatoVO> Consultar() {
        List<ContatoVO> lstAgenda = new ArrayList<ContatoVO>();

        //Consulta para trazer todos os dados da tabela Agenda ordenados pela coluna Nome
        Cursor cursor = database.query(BaseDAO.TBL_AGENDA, colunas, 
                null, null, null, null, BaseDAO.AGENDA_NOME);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            ContatoVO lContatoVO = cursorToContato(cursor);
            lstAgenda.add(lContatoVO);
            cursor.moveToNext();
        }
        
        //Tenha certeza que você fechou o cursor
        cursor.close();
        return lstAgenda;
    }

    //Converter o Cursor de dados no objeto POJO ContatoVO
    private ContatoVO cursorToContato(Cursor cursor) {
        ContatoVO lContatoVO = new ContatoVO();
        lContatoVO.setId(cursor.getLong(0));
        lContatoVO.setNome(cursor.getString(1));
        lContatoVO.setEndereco(cursor.getString(2));
        lContatoVO.setTelefone(cursor.getString(3));
        return lContatoVO;
    }
}


Arquivo ContatoAdapter.java, classe responsável por apresentar na tela em forma de ListView os contatos que estão memória que foram extraídos do Banco de Dados SQLite:
package br.com.Agenda.DAO;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
import br.com.Agenda.POJO.ContatoVO;
import br.com.Agenda.UI.R.id;
import br.com.Agenda.UI.R.layout;

public class ContatoAdapter extends BaseAdapter  {
    private Context context;

    private List<ContatoVO> lstContato;
    private LayoutInflater inflater;

    public ContatoAdapter(Context context, List<ContatoVO> listAgenda) {
        this.context = context;
        this.lstContato = listAgenda;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    
    //Atualizar ListView de acordo com o lstContato
    @Override
    public void notifyDataSetChanged() {   
        try{
            super.notifyDataSetChanged();
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }
    } 
        
    public int getCount() {
        return lstContato.size();
    }

    //Remover item da lista
    public void remove(final ContatoVO item) {
        this.lstContato.remove(item);
    } 
    
    //Adicionar item na lista
    public void add(final ContatoVO item) {
        this.lstContato.add(item);
    }    
    
    public Object getItem(int position) {
        return lstContato.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup viewGroup) {
        try
        {
            
            ContatoVO contato = lstContato.get(position);

            //O ViewHolder irá guardar a instâncias dos objetos do estado_row
            ViewHolder holder;
            
            //Quando o objeto convertView não for nulo nós não precisaremos inflar
            //os objetos do XML, ele será nulo quando for a primeira vez que for carregado
            if (convertView == null) {
                convertView = inflater.inflate(layout.contato_row, null);
                
                //Cria o Viewholder e guarda a instância dos objetos
                holder = new ViewHolder();
                holder.tvNome = (TextView) convertView.findViewById(id.txtNome);
                holder.tvEndereco = (TextView) convertView.findViewById(id.txtEndereco);
                holder.tvTelefone = (TextView) convertView.findViewById(id.txtTelefone);
                
                convertView.setTag(holder);
            } else {
                //pega o ViewHolder para ter um acesso rápido aos objetos do XML
                //ele sempre passará por aqui quando,por exemplo, for efetuado uma rolagem na tela 
                holder = (ViewHolder) convertView.getTag();
            }

            holder.tvNome.setText(contato.getNome());
            holder.tvEndereco.setText(contato.getEndereco());
            holder.tvTelefone.setText(contato.getTelefone());

            return convertView;            
            
        }catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }
        return convertView;
    }


    public void toast (String msg)
    {
        Toast.makeText (context, msg, Toast.LENGTH_SHORT).show ();
    } 
    
    private void trace (String msg) 
    {
        toast (msg);
    } 
    
    //Criada esta classe estática para guardar a referência dos objetos abaixo
    static class ViewHolder {
        public TextView tvNome;
        public TextView tvEndereco;
        public TextView tvTelefone;
    }    
}

Agora vamos ao resultado final desse projeto, abaixo serão apresentadas alguma figuras do comportamento do sistema.

1. Quando o sistema for executado pela primeira vez, ele deverá apresentar uma tela preta e apenas o botão para adicionar Contato.
2. Clicando no botão Adicionar o sistema deverá abrir a tela para inclusão de Contato, o usuário deverá informar os dados para cadastro e clicar em Confirmar.
3. Confirmando a inclusão do Contato, ao voltar para a primeira tela o sistema deverá apresentar automaticamente o contato cadastrado.
4. Clicando na primeira tela sobre um Contato cadastrado o sistema deverá apresentar uma caixa com as opções de Editar e Excluir o Contato ficando a cargo do usuário escolher a opção desejado.

Abaixo seguem as telas:

 




Vou terminando por aqui, caso tenham dúvidas, postem comentários, espero que tenham gostado do projeto apresentado ele é bem simples mas será a base para você criar projetos mais sofisticados.


Outras opções sobre ListView:

Parte 7 : http://escoladeandroid.blogspot.com.br/2012/03/android-listview-parte-7.html
Parte 8 : http://escoladeandroid.blogspot.com.br/2012/03/android-listview-parte-8.html

Carregando ListView com SqLite : http://escoladeandroid.blogspot.com.br/2012/04/android-carregando-listview-com-sqlite.html


Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.


Desenv com qualidade!