começando a desenvolver aplicativos para android

38
Começando a desenvolver aplicativos para Android 23 de março de 2010 1 comentário Este post é o primeiro de uma série em que vou ensinar, passo a passo, como criar um aplicativo para a plataforma android. Android é a plataforma do google para dispositivos móveis que equipa um grande número de telefones no mercado. (g1, motorola dext, milestone, nexus one…) O que preciso para começar a desenvolver para android? Uma idéia e força de vontade. E claro, saber programar em Java. Você NÃO precisa de um hardware (telefone) para isso. A grande maioria dos testes pode ser feito no emulador! Além disso, Android é uma plataforma de código aberto e o desenvolvimento de programas é amplamente incentivado pelo Google (e pela Motorola, como vamos ver no final do post). Por onde começar? O primeiro passo é montar seu ambiente de desenvolvimento. 1) Montar o ambiente padrão fornecido pelo Google. Para isso, você precisará seguir os seguintes passos: - Instalar o Eclipse (www.eclipse.org ) - Instalar o Android SDK (developer.android.com/sdk ) - Instalar o ADT Plugin (developer.android.com/sdk/eclipse- adt.html ) Todos os links contém as instruções para instalação dos componentes. Caso haja dúvidas, coloque nos comentários! DICA: Você pode “economizar” os passos acima usando o ambiente do Motodev que é basicamente a junção de todos os passos acima e mais algumas ferramentas. Para instalar o Motodev Studio vá até a página http://developer.motorola.com/docstools/motodevstudio/

Upload: paulovarela

Post on 26-Jun-2015

4.436 views

Category:

Documents


0 download

DESCRIPTION

Android é a plataforma do google para dispositivos móveis que equipa um grande número de telefones no mercado.

TRANSCRIPT

Page 1: Começando a desenvolver aplicativos para Android

Começando a desenvolver aplicativos para Android

23 de março de 2010 1 comentário

Este post é o primeiro de uma série em que vou ensinar, passo a passo, como criar um aplicativo para a plataforma android.

Android é a plataforma do google para dispositivos móveis que equipa um grande número de telefones no mercado. (g1, motorola dext, milestone, nexus one…)

O que preciso para começar a desenvolver para android?

Uma idéia e força de vontade. E claro, saber programar em Java. Você NÃO precisa de um hardware (telefone) para isso. A grande maioria dos testes pode ser feito no emulador!

Além disso, Android é uma plataforma de código aberto e o desenvolvimento de programas é amplamente incentivado pelo Google (e pela Motorola, como vamos ver no final do post).

Por onde começar?

O primeiro passo é montar seu ambiente de desenvolvimento.

1) Montar o ambiente padrão fornecido pelo Google. Para isso, você precisará seguir os seguintes passos:

- Instalar o Eclipse (www.eclipse.org)- Instalar o Android SDK (developer.android.com/sdk)- Instalar o ADT Plugin (developer.android.com/sdk/eclipse-adt.html)

Todos os links contém as instruções para instalação dos componentes. Caso haja dúvidas, coloque nos comentários!

DICA: Você pode “economizar” os passos acima usando o ambiente do Motodev – que é basicamente a junção de todos os passos acima e mais algumas ferramentas. Para instalar o Motodev Studio vá até a página http://developer.motorola.com/docstools/motodevstudio/

É importante dizer que os aplicativos gerados pelo Motodev Studio funcionarão em todos os telefones, e não só em telefones Motorola.

Page 2: Começando a desenvolver aplicativos para Android

Criando um projeto Android (Helloworld!)

No artigo da semana passada vimos como montar o ambiente de desenvolvimento android. Caso seu ambiente ainda não esteja funcionando, volte lá e veja o que faltou.

Hoje iremos criar nosso primeiro projeto android – o nosso “Helloworld”.

Passo 1 – Criando o projeto no Eclipse

Abra o Eclipse, vá até File>New>Project

Na tela que aparecer, escolha “Android Project” e clique em “Next”.

Criando um "Android Project"

Após isso, irá aparecer a tela com as configurações de seu projeto android.

Nesta tela, você precisa inserir os seguintes dados:

Project name - É o nome do projeto no eclipse. Build Target – É a versão do Android para a qual o seu projeto será direcionado. Application name – É o nome da sua aplicação – o nome que aparecerá no telefone. Package name -  É o package no qual serão criadas as suas classes java. Create Activity – Marque este checkbox e coloque um nome na caixa de texto. À

frente explicarei o que é uma Activity.

Depois disso, basta clicar em “Finish”.

Page 3: Começando a desenvolver aplicativos para Android

Configurando o projeto android

Passo 2 – Imprimindo um texto

Após isso, será criado um novo projeto e dentro dele, na pasta src/<nome_do_package>/ você encontrará um arquivo .java com o nome da Activity que você colocou no passo anterior.

Para fazer a sua aplicação imprimir um texto na tela, modifique este arquivo dessa forma:

view plain copy to clipboard print ?

1. package br.com.felipesilveira.hello_world;  2.   3. import android.app.Activity;  4. import android.os.Bundle;  5. import android.widget.TextView;  6.   7. public class HelloWorld extends Activity {  8.     /** Called when the activity is first created. */  9.     @Override  10.     public void onCreate(Bundle savedInstanceState) {  11.         super.onCreate(savedInstanceState);  12.         TextView view = new TextView(this);  13.         view.setText("Hello, Android");  14.         setContentView(view);  15.   16.     }  17. }  

Parte 3 – Rodando a aplicação no emulador

Para rodar nosso recém criado programa no emulador do google, vá até “Run”>Run as “Android Application”. Uma instância do emulador será criada, com o nosso “HelloWorld” rodando.

O que é uma Activity?

Neste HelloWorld tivemos contato com o primeiro elemento de um código android: A Activity.

Uma Activity é basicamente uma classe gerenciadora de UI (Interface com o usuário). Todo aplicativo android começa por uma Activity. Para saber mais, veja a documentação da classe Activity. Nos próximos artigos falaremos bastante sobre ela, suas características, seu ciclo de vida e como manipulá-la corretamente.

Page 4: Começando a desenvolver aplicativos para Android

DICA: Além de rodar a aplicação, você pode explorar um pouco o emulador, para conhecer o sistema operacional Android, caso ainda não conheça. Durante o desenvolvimento, o emulador será seu melhor amigo, então essa é a oportunidade para conhecê-lo bem.

Trabalhando com layouts XML em Android

Olá pessoal, hoje vou falar sobre a definição do layout de sua aplicação Android usando XML.

Definir os layouts através dessa técnica é a forma mais comum de se começar o desenvolvimento de uma aplicação.

Para exemplificar os estudos que faremos a partir de agora, usaremos uma aplicação de exemplo, que construiremos juntos, a partir dos próximos posts.

A idéia é fazer uma aplicação onde o usuário poderá entrar com algumas anotações, e visualizar as últimas entradas.

O layout será mais ou menos assim:

Criando o main.xml

Para novos projetos android, o arquivo main.xml já é automaticamente criado. Ele fica no diretório res/layout, com o conteúdo:

view plain copy to clipboard print ? 1. <?xml version="1.0" encoding="utf-8"?>  2. <LinearLayout xmlns:android="http://

schemas.android.com/apk/res/android"  3.  android:orientation="vertical"  4.  android:layout_width="fill_parent"  5.  android:layout_height="fill_parent"  6.  >  7. <TextView  8.  android:layout_width="fill_parent"  9.  android:layout_height="wrap_content"  

10.  android:text="@string/hello"  11.  />  12. </LinearLayout>  

Neste arquivo temos contato com os primeiros elementos de um arquivo de layout XML:

LinearLayout, que é apenas um container.

Page 5: Começando a desenvolver aplicativos para Android

TextView, que é um elemento de texto. Nesse caso está imprimindo a string cujo id é @string/hello. (Não se preocupe, falaremos sobre strings e seus ids à frente nesse curso)

Para criar um layout parecido com o rascunho do início do post, iremos inserir outros dois elementos:

EditText – uma caixa de texto onde o usuário irá entrar com as anotações; ListView – uma lista de anotações previamente submetidas.

Assim, o nosso novo XML:

view plain copy to clipboard print ? 1. <?xml version="1.0" encoding="utf-8"?>  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  3.  android:orientation="vertical"  4.  android:layout_width="fill_parent"  5.  android:layout_height="fill_parent"  6.  >  7.  <EditText  8.  android:id="@+id/edit_box"  9.  android:layout_width="fill_parent"  10.  android:layout_height="wrap_content"  11.  android:text="Nova nota..."  12.  >  13.  </EditText>  14.  <ListView  15.  android:id="@+id/notes_list"  16.  android:layout_width="fill_parent"  17.  android:layout_height="wrap_content"  18.  >  19.  </ListView>  20. </LinearLayout>  

Carregando o arquivo XML na aplicação

Para que a nossa aplicação tenha o layout definido pelo arquivo XML, é preciso carregá-lo.

Isso é feito através da função setContentView(), como no código abaixo:

view plain copy to clipboard print ? 1. public void onCreate(Bundle savedInstanceState) {  2.     super.onCreate(savedInstanceState);  3.     setContentView(R.layout.main);  4. }  

O parâmetro R.layout.main indica que o arquivo de layout a ser carregado é o main.xml. (Se o se arquivo se chamar abobrinha.xml, o parâmetro deverá ser R.layout.abobrinha)

Page 6: Começando a desenvolver aplicativos para Android

É possível utilizar mais de um arquivo XML para uma mesma tela, para formar layouts mais sofisticados. Trataremos disso à frente nesse curso.

Compilando o nosso projeto e rodando no emulador, temos o seguinte resultado:

QuickNotes rodando no emulador

No próximo post iremos acrescentar um botão a este layout, e iremos aprender um pouco mais sobre os parâmetros de um documento XML.

DICA: Existe uma ferramenta online, gratuita, para edição de arquivos de layout XML. É o DroidDraw.

LEITURA RECOMENDADA: Para aprender mais sobre a definição de layout de aplicações android, visite a página “User Interface” da documentação oficial. (em inglês)

Page 7: Começando a desenvolver aplicativos para Android

Adicionando um botão a um layout android

Para adicionar um botão clicável ao nosso layout, usaremos o widget Button.

Queremos que ele fique ao lado esquerdo da caixa de texto. Como fazer isso?

1. Diminuir o tamanho da caixa de texto. Para fazer isso, é só alterar a propriedade  android:layout_width. Originalmente o valor dela  era “fill_parent” – isso quer dizer: “ocupe todo o espaço disponível”. Ao invés disso, vamos usar 240 pixels.

2. Inserir o botão logo após a caixa de texto.3. Inserir um novo LinearLayout que irá conter a caixa de texto e o botão. Isso é

necessário porque o LinearLayout que definimos anteriormente (e que ocupa toda a tela) tem a propriedade android:orientation=”vertical”. Essa propriedade faz com que seus elementos sejam dispostos verticalmente (um debaixo do outro) e não é isso que queremos para estes dois elementos (a caixa de texto e o botão – queremos que fiquem lado a lado).

Assim, temos o nosso novo main.xml:

view plain copy to clipboard print ? 1. <?xml version="1.0" encoding="utf-8"?>  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  3. android:layout_width="fill_parent"  4. android:layout_height="fill_parent"  5. android:orientation="vertical"  6. >  7. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  8. android:layout_width="fill_parent"  9. android:layout_height="fill_parent"  10. >  11. <EditText  12. android:id="@+id/edit_box"  13. android:layout_width="240px"  14. android:layout_height="wrap_content"  15. android:text="Nova nota..."  16. >  17. </EditText>  18. <Button  19. android:id="@+id/insert_button"  20. android:layout_width="80px"  21. android:layout_height="wrap_content"  22. android:text="Inserir"  23. >  24. </Button>  25. </LinearLayout>  26. <ListView  27. android:id="@+id/notes_list"  28. android:layout_width="fill_parent"  29. android:layout_height="wrap_content"  

Page 8: Começando a desenvolver aplicativos para Android

30. >  31. </ListView>  32. </LinearLayout>  

Compilando as alterações, temos a seguinte tela:

Novo layout da aplicação android - agora com o botão "Inserir"

No próximo post veremos como controlar o botão de “inserir”.

Page 9: Começando a desenvolver aplicativos para Android

Activity – o que é isso?

Hoje iremos conhecer uma das mais importantes classes de uma aplicação Android: A classe Activity.

No post “Criando um projeto Android (Helloworld!)” comecei a falar sobre ela:

Uma Activity é basicamente uma classe gerenciadora de UI (Interface com o usuário). Todo aplicativo android começa por uma Activity.

Ou seja, quando uma aplicação android é executada, na verdade é a sua Activity principal que é lançada.

Ciclo de vida de uma Activity

Uma das coisas que é importante conhecer sobre a Activity é o seu ciclo de vida. E para explicá-lo, nada melhor do que o seguinte diagrama*:

Page 10: Começando a desenvolver aplicativos para Android

Ciclo de vida de uma Activity

Este diagrama é de fundamental importância para o correto entendimento do funcionamento de uma aplicação android. Ele introduz, implicitamente, os estados que uma Activity pode estar,  os quais explico no desenho abaixo:

Page 11: Começando a desenvolver aplicativos para Android

Estados de uma Activity

Voltando ao diagrama do ciclo de vida, temos as seguintes funções:

onCreate() É a primeira função a ser executada quando uma Activity é lançada. Geralmente é a responsável por carregar os layouts XML e outras operações de inicialização. É executada somente uma vez durante a “vida útil” da Activity.

onStart() É chamada imediatamente após a onCreate() – e também quando uma Activity que estava em background volta a ter foco.

onResume() Assim como a onStart(), é chamada na inicialização da Activity (logo após a própria onStart())  e também quando uma Activity volta a ter foco. Qual a diferença entre as duas? A onStart() só é chamada quando a Activity não estava mais visível na tela e volta a ter o foco, enquanto a onResume() sempre é chamada nas “retomadas de foco”.

onPause() É a primeira função a ser invocada quando a Activity perde o foco (ou seja, uma outra Activity vem à frente).

onStop() – Análoga à onStart(), só é chamada quando a Activity fica completamente encoberta por outra Activity (não é mais visível).

onDestroy() A última função a ser executada. Depois dela, a Activity é considerada “morta” – ou seja, nao pode mais ser relançada. Se o usuário voltar a requisitar essa Activity, outro objeto será contruído.

onRestart() Chamada imediatamente antes da onStart(), quando uma Activity volta a ter o foco depois de estar em background.

Executando uma Activity

Já sabemos que quando a sua aplicação é executada, a Activity definida como padrão (na criação do projeto) é lançada. Mas eu posso criar outras Activities?

É claro que sim.

Page 12: Começando a desenvolver aplicativos para Android

E para executar outras Activities, basta usar as funções startActivity() e startActivityForResult(). No exemplo abaixo, lançamos uma segunda Activity a partir da principal, e esperamos um resultado dela – como se fosse um retorno de função.

view plain copy to clipboard print ? 1.  static final int PICK_CONTACT_REQUEST = 0;  2.   3.   @Override  4.   public void onCreate(Bundle savedInstanceState) {  5.       super.onCreate(savedInstanceState);  6.       setContentView(R.layout.main);  7.       startActivityForResult(  8.               new Intent(Intent.ACTION_CONTACT_REQUEST,  9.               new Uri("content://contacts")),  10.               CONTACT_REQUEST);  11.   }  12.   13.   protected void onActivityResult(int requestCode, int resultCode,  14.                                             Intent data) {  15.       if (requestCode == CONTACT_REQUEST) {  16.    if (resultCode == RESULT_OK) {  17.           // fazer alguma coisa...  18.     }  19. }  

Quando a segunda Activity terminar a sua execução, a função onActivityResult() será invocada, com o “resultado” como parâmetro.

Mas como uma Activity define o seu resultado, a ser lido por aquela que a chamou?

Isso é feito invocando-se a função setResult (int resultCode), como por exemplo:

1. setResult(Intent.RESULT_OK);  

Alguém percebeu que eu não disse nada sobre os parâmetros da startActivityForResult()? Isso é porque este é o assunto do meu próximo post – o mecanismo de Uris em Android. Até lá!

Criando uma Activity secundária

6 de maio de 2010 5 comentários

No post passado vimos como lançar uma Activity a partir de outra, usando as funções startActivity() e startActivityForResult().

Hoje usaremos esta técnica para mostrar ao usuário uma tela de “Boas Vindas” na nossa aplicação de exemplo, o QuickNotes.

Page 13: Começando a desenvolver aplicativos para Android

Para criar essa nova Activity, usaremos alguma funções do Motodev. Se você não está usando a IDE da Motorola,  não tem problema – é só criar os arquivos manualmente. Porém recomendo o uso da IDE, por facilitar bastante a nossa vida.

Vamos começar criando a Activity que dará “Boas Vindas” ao usuário.

Vá até o menu “MOTODEV” >”New” > “New Android Activity”. Na tela de configuração, entre com o nome da Activity a ser criada:

Configurando a Activity a ser criada

Após clicar em “Finish”, já haverá a classe “WelcomeActivity” no diretório src do nosso projeto.

Com a Activity criada, o próximo passo é criar o arquivo XML que definirá o seu layout. Crie o arquivo ‘welcome.xml’ no diretorio res/layout com o seguinte conteúdo:

view plain copy to clipboard print ? 1. <?xml version="1.0" encoding="utf-8"?>  2. <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"  3. android:layout_width="fill_parent"  4. android:layout_height="fill_parent"  5. >  6. <TextView android:id="@+id/welcome_text_view"  7. android:layout_width="fill_parent"  8. android:layout_height="300dip"  9. android:gravity="center"  10. android:text="Bem vindo à aplicação QuickNotes!\n\nEssa aplicação foi feita duran

te o curso  11. 'Desenvolvendo para Android' do site felipesilveira.com.br"  12. >  13. </TextView>  14. <Button  

Page 14: Começando a desenvolver aplicativos para Android

15. android:id="@+id/welcome_ok_button"  16. android:layout_width="fill_parent"  17. android:layout_height="wrap_content"  18. android:text="Continuar"  19. >  20. </Button>  21. </TableLayout>  

Este arquivo XML define uma Activity com um texto e um botão logo abaixo, com a palavra “Continuar”.

Após criado o arquivo, vamos carregá-lo no método onCreate() da WelcomeActivity():

1. setContentView(R.layout.welcome);  

Lançando a WelcomeActivity

Para lançar a WelcomeActivity a partir da MainActivity, usaremos a função startActivity(). Esta função recebe como parâmetro um Intent. Posteriormente iremos aprofundar nosso conhecimento sobre essa importante classe, mas por enquanto o que você precisa saber é que ela é usada para fazer a comunicação entre Activities.

No código abaixo instanciamos um Intent cuja única função é lançar a WelcomeActivity, e então o usamos como parâmetro para a startActivity.

Dessa forma, o código da MainActivity fica assim:

view plain copy to clipboard print ? 1. package br.com.felipesilveira.quicknotes;  2.   3. import android.app.Activity;  4. import android.os.Bundle;  5. import android.content.Intent;  6.   7. public class MainActivity extends Activity {  8.     /** Called when the activity is first created. */  9.     @Override  10.     public void onCreate(Bundle savedInstanceState) {  11.         super.onCreate(savedInstanceState);  12.         setContentView(R.layout.main);  13.   14.         Intent i = new Intent(this, WelcomeActivity.class);  15.         startActivity(i);  16.      }  17. }  

Tratando os eventos de um botão

Até agora, já temos a Activity secundária sendo lançada, mas o que deve acontecer quando o usuário clicar no botão “Continuar”?

Page 15: Começando a desenvolver aplicativos para Android

A WelcomeActivity deve morrer - Dessa forma, a última Activity instanciada será mostrada novamente – que por sinal é a nossa MainAcitivity!

Para fazer isso, devemos adicionar um listener ao botão para que o método finish() seja invocado ao clique do usuário. O método finish() da classe Activity força a “morte” desta.

O código da WelcomeActivity fica assim:

view plain copy to clipboard print ? 1. package br.com.felipesilveira.quicknotes;  2.   3. import android.app.Activity;  4. import android.os.Bundle;  5. import android.view.View;  6. import android.widget.Button;  7.   8. public class WelcomeActivity extends Activity {  9.     /** 10.      * @see android.app.Activity#onCreate(Bundle) 11.      */  12.     @Override  13.     protected void onCreate(Bundle savedInstanceState) {  14.         super.onCreate(savedInstanceState);  15.         setContentView(R.layout.welcome);  16.   17.         final Button button = (Button) findViewById(R.id.welcome_ok_button);  18.   19.         button.setOnClickListener(new View.OnClickListener() {  20.             public void onClick(View v) {  21.                 finish();  22.             }  23.         });  24.     }  25. }  

Executando nosso projeto, temos a seguinte tela:

Page 16: Começando a desenvolver aplicativos para Android

WelcomeActivity sendo executada

Trabalhando com logs em android

13 de maio de 2010 Sem comentários

Hoje irei falar sobre um mecanismo simples porém muito útil para uma aplicação android: os logs.

Os logs permitem ao desenvolvedor debugar erros durante o desenvolvimento e também investigar problemas com o software em produção, ou seja, com o usuário final.

Para este fim, android tem um classe específica: A classe Log (android.util.Log).

Para criar os log, temos à disposição as funções Log.v(), Log.d(), Log.i(), Log.w(), r Log.e().

Mas por que tantas funções?

Porque os log em java tem alguns tipos – ou níveis – são eles:

Page 17: Começando a desenvolver aplicativos para Android

DEBUG – logs impressos pela função Log.d() ERROR – logs impressos pela função Log.e() INFO – logs impressos pela função Log.i() VERBOSE – logs impressos pela função Log.v() WARN – logs impressos pela função Log.w()

Todas estas funções recebem como parâmetros duas strings – a primeira, chamada de TAG, e a segunda que é a mensagem em si. A TAG é uma string que irá identificar a sua aplicação, tornando mais fácil identificar quais logs foram impressos por ela. (Todas as aplicações imprimem o log no mesmo stream. Assim, a única forma de separar os seus logs é filtrando pela sua Tag)

É uma boa prática definir a TAG como uma string constante:

view plain copy to clipboard print ? 1. private static final String TAG = "QuickNotesMainActivity";  

Dessa forma, para imprimir um log de DEBUG basta usar a linha abaixo:

view plain copy to clipboard print ? 1. Log.d(TAG, "mensagem de debug");  

Visualizando logs pelo DDMS

Para visualizar os logs de nossa aplicação, usaremos o DDMS. Abrindo a aba “Logcat”, temos a seguinte tela:

Lendo logs pelo logcat

Page 18: Começando a desenvolver aplicativos para Android

No ponto 1 marcado na imagem, temos os botões de “filtragem de níveis”. Estes botões permitem que você escolha quais logs quer ver – DEBUG, por exemplo. Já no ponto 3, você pode escrever um texto, que será um filtro para os logs. Por exemplo, se digitar “QuickNotesMainActivity”, irá ver só os logs que nós colocamos no código acima.

Finalmente, no ponto 2 temos a mensagem de log em si.

DICA: Seja cuidadoso com os logs. Eles podem interferir na performance de sua aplicação se, por exemplo, forem colocados dentro de um loop.

Content Providers

Os Content Providers são parte importantíssima da arquitetura de um sistema android. É responsabilidade deles prover às aplicações o conteúdo que elas precisam para funcionar, ou seja, os dados.

Mas por que são realmente necessários?

As aplicações poderiam muito bem acessar diretamente um banco de dados, por exemplo. Porém, é uma boa prática tornar o modo como os dados são gravados transparente à aplicação. Dessa forma, a aplicação pode manter o foco nas interações com o usuário.

Além disso, essa técnica permite a criação de Shared Content Providers, que são providers “públicos” que podem ser acessados por várias aplicações. Por exemplo, existe o content provider de SMS/MMS que permite a qualquer aplicação ler as mensagens recebidas por um telefone celular.

E como é feita a comunicação entre Content Providers e Aplicações?

Uri. Guarde bem este nome, pois você irá precisar muito dele durante a sua carreira como desenvolvedor android.

Toda a comunicação entre aplicações e providers é feita através dos métodos da interface ContentProvider, que sempre recebem um objeto Uri como parâmetro. O formato da Uri é definido pelo content provider. Por exemplo, a Uri content://sms/inbox acessa as mensagens de inbox no Content Provider de SMS. Falaremos um pouco mais sobre as Uris a seguir, mas primeiro, vamos conhecer os métodos que usaremos para enviá-las para o provider:

query(Uri, String[], String, String[], String)- usado para recuperar dados.

insert(Uri, ContentValues) – usado para inserir dados. update(Uri, ContentValues, String, String[]) – usado para atualizar

dados. delete(Uri, String, String[]) – usado para deletar dados. getType(Uri) – usado para obter o MIME type de certo dado.

Page 19: Começando a desenvolver aplicativos para Android

O QuickNotes Content Provider

Depois dessa rápida introdução, vamos colocar a mão na massa.

Iremos criar um content provider para o QuickNotes, que servirá para gravar e recuperar as anotações do usuário, da seguinte forma:

Intencionalmente coloquei a caixa que define como o provider irá gravar os dados para mostrar que isso é irrelevante para a aplicação.

A estrutura das URIs

Uma Uri usada para acessar Content Provider segue o formato:

content://<authority>/<parametro1>/<parametro2>/…/<parametroN>

Onde authority é o “nome” do provider, e os parâmetros são aqueles definidos pelo provider. Por exemplo, a seguinte Uri:

content://sms/conversations/10

Acessa o Content Provider de SMS, e seleciona a conversation de Id número 10.

Criando um Content Provider

Para criar seu próprio content provider, é preciso fazer 2 coisas:

1. Criar uma sub-classe da ContentProvider, implementando os métodos públicos que eu citei no começo do artigo;

2. Registrar o provider no AndroidManifest.xml

Vamos começar criando a classe QuickNotesProvider:

view plain copy to clipboard print ? 1. package br.com.felipesilveira.quicknotes;  2.   3. import android.content.ContentProvider;  4. import android.net.Uri;  5. import android.content.ContentValues;  

Page 20: Começando a desenvolver aplicativos para Android

6. import android.database.Cursor;  7.   8. public class QuickNotesProvider extends ContentProvider {  9.     // Aqui definimos os formatos possíveis de Uri que  10.     // o nosso provider irá aceitar.  11.     public static final Uri CONTENT_URI = Uri  12. .parse("content://br.com.felipesilveira.quicknotes.quicknotesprovider");  13.   14.     @Override  15.     public int delete(Uri uri, String selection, String[] selectionArgs) {  16.         return 0;  17.     }  18.   19.     @Override  20.     public String getType(Uri uri) {  21.         return null;  22.     }  23.   24.     @Override  25.     public Uri insert(Uri uri, ContentValues values) {  26.         return null;  27.     }  28.   29.     @Override  30.     public boolean onCreate() {  31.         return false;  32.     }  33.   34.     @Override  35.     public Cursor query(Uri uri, String[] projection, String selection,  36.             String[] selectionArgs, String sortOrder) {  37.         return null;  38.     }  39.   40.     @Override  41.     public int update(Uri uri, ContentValues values, String selection,  42.             String[] selectionArgs) {  43.         return 0;  44.     }  45. }  

Agora, vamos registrar o nosso provider no AndroidManifest, adicionando a seguinte linha entre as tags <application …> e </application>

<providerandroid:authorities="br.com.felipesilveira.quicknotes.quicknotesprovider"android:name=".QuickNotesProvider"/>

E assim o nosso Content Provider está pronto para receber requisições da aplicação. Ainda não retorna nenhum resultado significativo – mas isso faremos no próximo artigo, onde

Page 21: Começando a desenvolver aplicativos para Android

ensinarei como acessar um banco de dados SQLite, para fazer esse provider realmente efetivo.

DICA: Usando o MOTODEV Studio, a tarefa de criar um content provider fica muito mais fácil. Basta acessar New > Android Content Provider, que um template será criado, com todos os métodos! daí é só implementar a lógica deles.

Como usar banco de dados em uma aplicação android

Um dos grandes diferenciais da plataforma android é a grande quantidade de módulos e APIs que as aplicações tem à  disposição para usar. Eles dão muito poder ao desenvolvedores, permitindo que estes façam coisas que eram impossíveis em outras plataformas móveis.

Um dos mais importantes módulos é o SQLite. Sim, amigos, já temos um SGDB (Sistema gerenciador de bancos de dados) instalado e pronto para usar! E é exatamente o que faremos no artigo de hoje.

No artigo anterior vimos como criar um Content Provider. Usaremos este provider para acessar o banco de dados.

Para fazer isso, precisamos implementar os métodos da classe ContentProvider que vimos no artigo passado (query(), delete(), update(), etc…)  para prover ao usuário os métodos para criar, atualizar, deletar e recuperar os dados. Além disso, usaremos a classe SQLiteOpenHelper para gerenciar a conexão com o banco de dados.

A classe SQLiteOpenHelper

A classe SQLiteOpenHelper, como dito anteriormente, será usada para gerenciar o banco de dados. Para usá-la, é preciso criar uma subclasse implementando os métodos abaixo:

onCreate() – Este método é chamado quando a conexão com o banco de dados for aberta pela primeira vez. É aqui que criaremos o banco de dados, com o comando sql CREATE.

onUpdate() – Este método é chamado quando a versão do banco de dados muda. Por exemplo, digamos que você criou uma nova versão de seu aplicativo que usa uma tabela a mais no banco de dados. Quando esta nova versão for instalada (em um telefone que já possuir a primeira versão) este método será chamado, então você poderá criar apenas a nova  tabela, mantendo os dados do usuário.

O código

O código do QuickNotesProvider fica assim, acessando o banco de dados. A seguir, eu explico algumas coisas que podem gerar dúvidas.

view plain copy to clipboard print ? 1. package br.com.felipesilveira.quicknotes;  2.   3. import java.util.HashMap;  4.   

Page 22: Começando a desenvolver aplicativos para Android

5. import android.content.ContentProvider;  6. import android.content.ContentUris;  7. import android.content.Context;  8. import android.content.UriMatcher;  9. import android.net.Uri;  10. import android.provider.BaseColumns;  11. import android.content.ContentValues;  12. import android.database.Cursor;  13. import android.database.sqlite.SQLiteDatabase;  14. import android.database.sqlite.SQLiteOpenHelper;  15. import android.database.sqlite.SQLiteQueryBuilder;  16.   17. public class QuickNotesProvider extends ContentProvider {  18.   19.     // Authority do nosso provider, a ser usado nas Uris.  20.     public static final String AUTHORITY =  21.         "br.com.felipesilveira.quicknotes.quicknotesprovider";  22.   23.     // Nome do arquivo que irá conter o banco de dados.  24.     private static  final String DATABASE_NAME = "quicknotes.db";  25.   26.     // Versao do banco de dados.  27.     // Este valor é importante pois é usado em futuros updates do DB.  28.     private static  final int  DATABASE_VERSION = 1;  29.   30.     // Nome da tabela que irá conter as anotações.  31.     private static final  String NOTES_TABLE = "notes";  32.   33.     // 'Id' da Uri referente às notas do usuário.  34.     private  static final int NOTES = 1;  35.   36.     // Tag usada para imprimir os logs.  37.     public static final String TAG = "QuickNotesProvider";  38.   39.     // Instância da classe utilitária  40.     private DBHelper mHelper;  41.   42.     // Uri matcher - usado para extrair informações das Uris  43.     private static final UriMatcher mMatcher;  44.   45.     private static HashMap<string, string=""> mProjection;  46.   47.     static {  48.         mProjection = new HashMap<string, string="">();  49.         mProjection.put(Notes.NOTE_ID, Notes.NOTE_ID);  50.         mProjection.put(Notes.TEXT, Notes.TEXT);  51.     }  52.   53.     static {  54.         mMatcher = new UriMatcher(UriMatcher.NO_MATCH);  

Page 23: Começando a desenvolver aplicativos para Android

55.         mMatcher.addURI(AUTHORITY, NOTES_TABLE, NOTES);  56.     }  57.   58.     /////////////////////////////////////////////////////////////////  59.     //           Métodos overrided de ContentProvider              //  60.     /////////////////////////////////////////////////////////////////  61.     @Override  62.     public int delete(Uri uri, String selection, String[] selectionArgs) {  63.         SQLiteDatabase db = mHelper.getWritableDatabase();  64.         int count;  65.         switch (mMatcher.match(uri)) {  66.             case NOTES:  67.                 count = db.delete(NOTES_TABLE, selection, selectionArgs);  68.                 break;  69.             default:  70.                 throw new IllegalArgumentException(  71.                   "URI desconhecida " + uri);  72.         }  73.   74.         getContext().getContentResolver().notifyChange(uri, null);  75.         return count;  76.     }  77.   78.     @Override  79.     public String getType(Uri uri) {  80.             switch (mMatcher.match(uri)) {  81.                 case NOTES:  82.                     return Notes.CONTENT_TYPE;  83.                 default:  84.                     throw new IllegalArgumentException(  85.                         "URI desconhecida " + uri);  86.             }  87.     }  88.   89.     @Override  90.     public Uri insert(Uri uri, ContentValues values) {  91.         switch (mMatcher.match(uri)) {  92.             case NOTES:  93.                 SQLiteDatabase db = mHelper.getWritableDatabase();  94.                 long rowId = db.insert(NOTES_TABLE, Notes.TEXT, values);  95.                 if (rowId > 0) {  96.                     Uri noteUri = ContentUris.withAppendedId(  97.                                  Notes.CONTENT_URI, rowId);  98.                     getContext().getContentResolver().notifyChange(  99.                                  noteUri, null);  100.                     return noteUri;  101.                 }  102.             default:  103.                 throw new IllegalArgumentException(  104.                         "URI desconhecida " + uri);  

Page 24: Começando a desenvolver aplicativos para Android

105.         }  106.     }  107.   108.     @Override  109.     public boolean onCreate() {  110.         mHelper = new DBHelper(getContext());;  111.         return true;  112.     }  113.   114.     @Override  115.     public Cursor query(Uri uri, String[] projection, String selection,  116.             String[] selectionArgs, String sortOrder) {  117.             // Aqui usaremos o SQLiteQueryBuilder para construir  118.             // a query que será feito ao DB, retornando um cursor  119.             // que enviaremos à aplicação.  120.             SQLiteQueryBuilder builder = new  SQLiteQueryBuilder();  121.             SQLiteDatabase database = mHelper.getReadableDatabase();  122.             Cursor cursor;  123.             switch (mMatcher.match(uri)) {  124.                 case NOTES:  125.                     // O Builer receberá dois parametros: a tabela  126.                     // onde será feita a busca, e uma projection -  127.                     // que nada mais é que uma HashMap com os campos  128.                     // que queremos recuperar do banco de dados.  129.                     builder.setTables(NOTES_TABLE);  130.                     builder.setProjectionMap(mProjection);  131.                     break;  132.   133.                 default:  134.                     throw new IllegalArgumentException(  135.                           "URI desconhecida " + uri);  136.             }  137.   138.             cursor = builder.query(database, projection, selection,  139.              selectionArgs, null, null, sortOrder);  140.   141.             cursor.setNotificationUri(getContext().getContentResolver(), uri);  142.             return cursor;  143.     }  144.   145.     @Override  146.     public int update(Uri uri, ContentValues values, String selection,  147.             String[] selectionArgs) {  148.             SQLiteDatabase db = mHelper.getWritableDatabase();  149.             int count;  150.             switch (mMatcher.match(uri)) {  151.                 case NOTES:  152.                     count = db.update(NOTES_TABLE, values,  153.                                                      selection, selectionArgs);  154.                     break;  

Page 25: Começando a desenvolver aplicativos para Android

155.                 default:  156.                     throw new IllegalArgumentException(  157.                             "URI desconhecida " + uri);  158.             }  159.   160.             getContext().getContentResolver().notifyChange(uri, null);  161.             return count;  162.     }  163.   164.     /////////////////////////////////////////////////////////////////  165.     //                Inner Classes utilitárias                    //  166.     /////////////////////////////////////////////////////////////////  167.     public static final class  Notes implements  BaseColumns {  168.         public static final Uri CONTENT_URI = Uri.parse("content://"  169.                     + QuickNotesProvider.AUTHORITY + "/notes");  170.   171.         public static final String CONTENT_TYPE =  172.                 "vnd.android.cursor.dir/" + QuickNotesProvider.AUTHORITY;  173.   174.         public static final String NOTE_ID = "_id";  175.   176.         public static final String TEXT = "text";  177.     }  178.   179.     private static class DBHelper extends SQLiteOpenHelper {  180.   181.         DBHelper(Context context) {  182.             super(context, DATABASE_NAME, null, DATABASE_VERSION)

;  183.         }  184.   185.         /* O método onCreate é chamado quando o provider é executado pela 186.          * primeira vez, e usado para criar as tabelas no database 187.          */  188.         @Override  189.         public void onCreate(SQLiteDatabase db) {  190.             db.execSQL("CREATE TABLE " + NOTES_TABLE + " (" +  191.                     Notes.NOTE_ID + " INTEGER PRIMARY KEY AUTOINCR

EMENT," +  192.                     Notes.TEXT + " LONGTEXT" + ");");  193.         }  194.   195.         /* O método onUpdate é invocado quando a versão do banco de dados 196.          * muda. Assim, é usado para fazer adequações para a aplicação 197.          * funcionar corretamente. 198.          */  199.         @Override  200.         public void onUpgrade(SQLiteDatabase db,  201.                                       int oldVersion, int newVersion) {  202.             // Como ainda estamos na primeira versão do DB,  

Page 26: Começando a desenvolver aplicativos para Android

203.             // não precisamos nos preocupar com o update agora.  204.         }  205.     }  206. }  207. </string,></string,>  

Cursores

O primeiro conceito importante a se falar é o conceito dos Cursores. Como você deve percebido, este é o tipo de retorno do método query(), e não é por acaso: Os cursores são “apontadores de dados” do banco de dados – ou seja, uma interface que permite o acesso aos dados retornados pela query enviada pelo usuário.

notifyChanges()

Em todos os métodos em que alteramos o banco de dados (inserimos, deletamos ou modificamos dados) é importante chamar o método modifyChanges(). Isso fará com que as aplicações que estejam utilizando este conjunto de dados sejam notificadas, permitindo a estas atualizar também os dados mostrados ao usuário.

Acessando um Content Provider

No artigo de hoje começaremos a integrar a nossa aplicação QuickNotes com o QuickNotesProvider, que criamos no artigo anterior.

Vamos começar inserindo uma anotação do usuário no banco de dados. Para fazer isso, o primeiro passo é adicionar um Listener ao botão ‘Inserir’, da seguinte forma:

1. Button insertButton = (Button)findViewById(R.id.insert_button);  2. insertButton.setOnClickListener(mInsertListener);  

E agora, criando o objeto mInsertListener. Ele precisa ser um objeto que implementa a interface OnClickListener,. Assim, precisamos implementar o método onClick(), que será chamado assim que o usuário pressionar o botão.

view plain copy to clipboard print ? 1. // Definindo um OnClickListener para o botão "Inserir"  2. private OnClickListener mInsertListener = new OnClickListener() {  3.      public void onClick(View v) {  4.          EditText editBox = (EditText)findViewById(R.id.edit_box);  5.          addNote(editBox.getText().toString());  6.          editBox.setText("");  7.      }  8. };  

No código acima eu fiz uma chamada a um método que ainda não está implementado – o método addNote(), que recebe um String que será inserida no banco de dados. Ele será o método responsável por efetivamente “conversar” com o content provider. Vamos implementá-lo:

Page 27: Começando a desenvolver aplicativos para Android

view plain copy to clipboard print ? 1.     /* 2.     * Método responsável por inserir um registro no content provider 3.     */  4.       protected void addNote(String text) {  5.           ContentValues values = new ContentValues();  6.           values.put(QuickNotesProvider.Notes.TEXT, text);    7.   8.           getContentResolver().insert(  9.                           QuickNotesProvider.Notes.CONTENT_URI, values);  10. }  

Assim, a MainActivity fica dessa forma:

view plain copy to clipboard print ? 1. package br.com.felipesilveira.quicknotes;  2.   3. import android.app.Activity;  4. import android.os.Bundle;  5. import android.view.View;  6. import android.view.View.OnClickListener;  7. import android.widget.Button;  8. import android.widget.EditText;  9. import android.content.ContentValues;  10. import android.content.Intent;  11.   12. public class MainActivity extends Activity {  13.   14.     private static final String TAG = "QuickNotesMainActivity";  15.   16.     /** Called when the activity is first created. */  17.     @Override  18.     public void onCreate(Bundle savedInstanceState) {  19.         super.onCreate(savedInstanceState);  20.         setContentView(R.layout.main);  21.   22.         Intent i = new Intent(this, WelcomeActivity.class);  23.         startActivity(i);  24.   25.         Button insertButton = (Button)findViewById(R.id.insert_button);  26.         insertButton.setOnClickListener(mInsertListener);  27.   28.         // adicionando um 'Hint' ao Editbox.  29.         EditText editBox = (EditText)findViewById(R.id.edit_box);  30.         editBox.setHint("Nova nota...");  31.      }  32.   33.      // Definindo um OnClickListener para o botão "Inserir"  34.      private OnClickListener mInsertListener = new OnClickListener() {  35.           public void onClick(View v) {  

Page 28: Começando a desenvolver aplicativos para Android

36.               EditText editBox = (EditText)findViewById(R.id.edit_box);  37.               addNote(editBox.getText().toString());  38.               editBox.setText("");  39.           }  40.      };  41.   42.      /* 43.       * Método responsável por inserir um registro no content provider 44.       */  45.      protected void addNote(String text) {  46.          ContentValues values = new ContentValues();  47.          values.put(QuickNotesProvider.Notes.TEXT, text);    48.   49.          getContentResolver().insert(  50.               QuickNotesProvider.Notes.CONTENT_URI, values);  51.      }  52. }  

É importante salientar que estamos apenas inserindo o dado no banco de dados – não estamos lendo-o em nenhum lugar na nossa aplicação, ainda.

Mas como saber se o dado realmente foi inserido no banco de dados?

Vou aproveitar esta pergunta para mostrar como acessar o banco de dados pelo shell do android. Isso é muito útil para auxiliar no desenvolvimento de aplicações que lidam com banco de dados.

Acessando banco de dados através do shell

Para acessar o banco de dados pelo shell, iremos iniciar uma sessão com o comando adb shell e então usar o comando sqlite3 <caminho-do-db>. A partir daí, basta usar comandos SQL normais. Para ver a estrutura do banco de dados, o comando .schema deve ser usado. Veja no exemplo abaixo:

$ adb shell# sqlite3 /data/data/br.com.felipesilveira.quicknotes/databases/quicknotes.dbSQLite version 3.5.9Enter “.help” for instructionssqlite> .schema.schemaCREATE TABLE android_metadata (locale TEXT);CREATE TABLE notes (_id INTEGER PRIMARY KEY AUTOINCREMENT,text LONGTEXT);sqlite> select * from notes;select * from notes;1|teste

Como podemos ver, a primeira entrada do nosso DB está lá, então é sinal que o QuickNotesProvider está funcionando corretamente!

Page 29: Começando a desenvolver aplicativos para Android

No próximo artigo, iremos usar o provider para ler os dados já gravados no DB para mostrá-los ao usuário. Até lá!