You are on page 1of 21

Android a plataforma do google para dispositivos mveis que equipa um grande nmero de telefones no mercado.

. (g1, motorola dext, milestone, nexus one) O que preciso para comear a desenvolver para android? Uma idia e fora de vontade . E claro, saber programar em Java. Voc NO precisa de um hardware (telefone) para isso. A grande maioria dos testes pode ser feito no emulador! Alm disso, Android uma plataforma de cdigo aberto e o desenvolvimento de programas amplamente incentivado pelo Google (e pela Motorola, como vamos ver no final do post). Por onde comear? O primeiro passo montar seu ambiente de desenvolvimento. 1) Montar o ambiente padro 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 contm as instrues para instalao dos componentes. Caso haja dvidas, coloque nos comentrios! DICA: Voc pode economizar os passos acima usando o ambiente do Motodev que basicamente a juno de todos os passos acima e mais algumas ferramentas. Para instalar o Motodev Studio v at a pgina http://developer.motorola.com/docstools/motodevstudio/ importante dizer que os aplicativos gerados pelo Motodev Studio funcionaro em todos os telefones, e no s em telefones Motorola.

Criando um projeto Android (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"

Aps isso, ir aparecer a tela com as configuraes de seu projeto android. Nesta tela, voc precisa inserir os seguintes dados:

Project name - o nome do projeto no eclipse. Build Target a verso do Android para a qual o seu projeto ser direcionado. Application name o nome da sua aplicao o nome que aparecer no telefone. Package name - o package no qual sero 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.

Configurando o projeto android

Passo 2 Imprimindo um texto


Aps 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 aplicao imprimir um texto na tela, modifique este arquivo dessa forma:
view plaincopy to clipboardprint?

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 aplicao no emulador


Para rodar nosso recm criado programa no emulador do google, v at Run>Run as Android Application. Uma instncia do emulador ser criada, com o nosso HelloWorld rodando.

Hello World rodando no emulador

O que uma Activity?


Neste HelloWorld tivemos contato com o primeiro elemento de um cdigo android: A Activity. Uma Activity basicamente uma classe gerenciadora de UI (Interface com o usurio). Todo aplicativo android comea por uma Activity. Para saber mais, veja a documentao da classeActivity. Nos prximos artigos falaremos bastante sobre ela, suas caractersticas, seu ciclo de vida e como manipul-la corretamente. DICA: Alm de rodar a aplicao, voc pode explorar um pouco o emulador, para conhecer o sistema operacional Android, caso ainda no conhea. Durante o desenvolvimento, o emulador ser seu melhor amigo, ento essa a oportunidade para conhec-lo bem.

Criando uma Activity secundria


No post passado vimos como lanar uma Activity a partir de outra, usando as funesstartActivity() e startActivityForResult(). Hoje usaremos esta tcnica para mostrar ao usurio uma tela de Boas Vindas na nossa aplicao de exemplo, o QuickNotes. Para criar essa nova Activity, usaremos alguma funes do Motodev. Se voc no est usando a IDE da Motorola, no tem problema s criar os arquivos manualmente. Porm recomendo o uso da IDE, por facilitar bastante a nossa vida. Vamos comear criando a Activity que dar Boas Vindas ao usurio. V at o menu MOTODEV >New > New Android Activity. Na tela de configurao, entre com o nome da Activity a ser criada:

Configurando a Activity a ser criada

Aps clicar em Finish, j haver a classe WelcomeActivity no diretrio src do nosso projeto. Com a Activity criada, o prximo passo criar o arquivo XML que definir o seu layout. Crie o arquivo welcome.xml no diretorio res/layout com o seguinte contedo:
view plaincopy to clipboardprint?

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 aplicao QuickNotes!\n\nEssa aplicao foi feita durant
e o curso

11. 'Desenvolvendo para Android' do site felipesilveira.com.br" 12. > 13. </TextView> 14. <Button 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 boto logo abaixo, com a palavra Continuar. Aps criado o arquivo, WelcomeActivity(): vamos carreg-lo no mtodo onCreate() da

1. setContentView(R.layout.welcome);

Lanando a WelcomeActivity
Para lanar a WelcomeActivity a partir da MainActivity, usaremos a funo startActivity(). Esta funo recebe como parmetro 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 comunicao entre Activities. No cdigo abaixo instanciamos um Intent cuja nica funo lanar a WelcomeActivity, e ento o usamos como parmetro para a startActivity. Dessa forma, o cdigo da MainActivity fica assim:
view plaincopy to clipboardprint?

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 boto


At agora, j temos a Activity secundria sendo lanada, mas o que deve acontecer quando o usurio clicar no boto Continuar? 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 boto para que o mtodo finish() seja invocado ao clique do usurio. O mtodo finish() da classe Activity fora a morte desta. O cdigo da WelcomeActivity fica assim:
view plaincopy to clipboardprint?

1. package br.com.felipesilveira.quicknotes;
2.

3. 4. 5. 6.
7.

import import import import

android.app.Activity; android.os.Bundle; android.view.View; android.widget.Button;

8. public class WelcomeActivity extends Activity {

9. 10. 11. 12. 13. 14. 15.


16. 18.

/** * @see android.app.Activity#onCreate(Bundle) */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.welcome); final Button button = (Button) findViewById(R.id.welcome_ok_button);

17.

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:

WelcomeActivity sendo executada

Criando uma ListActivity


Hoje aprenderemos a usar uma ListActivity para mostrar ao usuario uma lista com as anotaes que ele inseriu em nossa aplicao QuickNotes.

ListActivity? O que isso? A ListActivity uma classe filha da Activity cujo objetivo mostrar ao usurio uma Lista (umaListView). Em suma, uma Activity com alguns mtodos para gerenciamento de listas, criada com o intuito de facilitar a criao de telas com essa configurao, muito comuns nas aplicaes android. O primeiro passo para criar uma Activity desse tipo assegurar que o layout XML a ser usado por ela possui um elemento ListView (afinal, estamos criando uma ListActivity!). Alm disso, preciso que seu id seja @id/android:list. Adequando o layout da nossa aplicao, temos:
view plaincopy to clipboardprint?

1. <!--?xml version="1.0" encoding="utf-8" ?--> 2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" andr


oid:layout_width="fill_parent" android:layout_height="fill_parent" android:orientatio n="vertical"> 3. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" an droid:layout_width="fill_parent" android:layout_height="wrap_content"> 4. <edittext android:id="@+id/edit_box" android:layout_width="240px" android :layout_height="wrap_content" android:text=""> 5. </edittext> 6. <button android:id="@+id/insert_button" android:layout_width="80px" andr oid:layout_height="wrap_content" android:text="Inserir"> 7. </button> 8. </linearlayout> 9. <listview android:id="@android:id/list" android:layout_width="fill_parent" andro id:layout_height="fill_parent"> 10. </listview> 11. </linearlayout>

Depois disso, o prximo fazer a nossa classe MainActivity ser uma classe filha da ListActivity: public class MainActivity extends ListActivity E ento, inicializar a ListView no mtodo onCreate. Mas para isso precisaremos de um Adapter.

Adapters
Adapters so classes responsveis por fazer o que chamado de bind: Receber os dados de um Cursor (ou de alguma outra fonte de dados) e coloclos nos seus respectivos lugares no layout da Activity. Para Activitys complexas, tipicamente so criadas subclasses da classe CursorAdapter (Adapter dedicado a tratar cursores). No nosso caso, em que temos um layout bastante simples, suficiente o uso do SimpleCursorAdapter. No cdigo abaixo eu mostro como usar este adapter, com uma explicao sobre seus parmetros:
view plaincopy to clipboardprint?

1. ListAdapter adapter = new SimpleCursorAdapter( 2. // O primeiro parametro eh o context. 3. this, 4. // O segundo, o layout de cada item. 5. R.layout.list_item,

6. 7. 8. 9. 10. 11. 12. 13. 14. 15.


16.

// O terceiro parametro eh o cursor que contem os dados // a serem mostrados mCursor, // o quarto parametro eh um array com as colunas do // cursor que serao mostradas new String[] {QuickNotesProvider.Notes.TEXT}, // o quinto parametro eh um array (com o mesmo // tamanho do anterior) com os elementos que // receberao os dados. new int[] {R.id.text});

17. setListAdapter(adapter);
Um dos parmetros recebidos pelo contrutor da SimpleCursorAdapter o layout dos itens da lista, que definimos da seguinte forma:
view plaincopy to clipboardprint?

1. <!--?xml version="1.0" encoding="utf-8" ?--> 2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" andr


oid:layout_width="fill_parent" android:layout_height="wrap_content" android:orient ation="vertical"> 3.

4. 5.

<textview android:id="@+id/text" android:textsize="16sp" android:textstyle=" bold" android:textcolor="#FFFFFF" android:layout_width="fill_parent" android:layo ut_height="wrap_content"> </textview></linearlayout>

E por fim, a nossa Activity principal fica assim:


view plaincopy to clipboardprint?

1. package br.com.felipesilveira.quicknotes;
2.

3. import android.app.ListActivity; 4. import android.os.Bundle; 5. import android.util.Log; 6. import android.view.View; 7. import android.view.View.OnClickListener; 8. import android.widget.Button; 9. import android.widget.EditText; 10. import android.widget.ListAdapter; 11. import android.widget.SimpleCursorAdapter; 12. import android.content.ContentValues; 13. import android.content.Intent; 14. import android.database.Cursor;
15. 17.

16. public class MainActivity extends ListActivity { 18. 19.


20. private static final String TAG = "QuickNotesMainActivity"; private Cursor mCursor; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "Criando a MainActivity"); setContentView(R.layout.main);

21. 22. 23. 24.


25. 27. 29.

26. 28.

30. 31.
32.

Intent i = new Intent(this, WelcomeActivity.class); startActivity(i); Button insertButton = (Button)findViewById(R.id.insert_button); insertButton.setOnClickListener(mInsertListener); // adicionando um 'Hint' ao Editbox. EditText editBox = (EditText)findViewById(R.id.edit_box); editBox.setHint("Nova nota..."); mCursor = this.getContentResolver(). query(QuickNotesProvider.Notes.CONTENT_URI, null, null, null, null); ListAdapter adapter = new SimpleCursorAdapter( // O primeiro parametro eh o context. this, // O segundo, o layout de cada item. R.layout.list_item, // O terceiro parametro eh o cursor que contem os dados // a serem mostrados mCursor, // o quarto parametro eh um array com as colunas do // cursor que serao mostradas new String[] {QuickNotesProvider.Notes.TEXT}, // o quinto parametro eh um array (com o mesmo // tamanho do anterior) com os elementos que // receberao os dados. new int[] {R.id.text}); setListAdapter(adapter); } /* * Definindo um OnClickListener para o boto "Inserir" */ private OnClickListener mInsertListener = new OnClickListener() { public void onClick(View v) { EditText editBox = (EditText)findViewById(R.id.edit_box); addNote(editBox.getText().toString()); editBox.setText(""); } }; /* * Mtodo responsvel por inserir um registro no content provider */ protected void addNote(String text) { ContentValues values = new ContentValues(); values.put(QuickNotesProvider.Notes.TEXT, text);

33. 34.
35.

36. 37. 38.


39. 41. 42.

40. 43. 44. 45. 46. 47.


48. 49. 51. 53.

50. 52. 54. 55. 56. 57.


58.

10

59. 60.
61. 62. 64.

63. 65. 66. 67. 68. 69. 70. 71.


72. 73. 74. 75.

76. 77. 78.


79.

80. getContentResolver().insert( 81. QuickNotesProvider.Notes.CONTENT_URI, values); 82. } 83. }


Executando a Activity, temos a seguinte tela, com a lista das notas que o usurio digitou!

11

DICA: Tenha muito cuidado ao projetar uma lista. Lembre-se que um usurio pode inserir mil, dez mil registros! O qeu aconteceria nessa situao? A performance nesses casos um fator a ser muito trabalhado e testado. Mas isso fica para um prximo artigo. At l!

Como usar banco de dados em uma aplicao android


Um dos grandes diferenciais da plataforma android a grande quantidade de mdulos e APIs que as aplicaes tem disposio para usar. Eles do muito poder ao desenvolvedores, permitindo que estes faam coisas que eram impossveis em outras plataformas mveis. Um dos mais importantes mdulos 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 mtodos da classe ContentProvider que vimos no artigo passado (query(), delete(), update(), etc) para prover ao usurio os mtodos para criar, atualizar, deletar

e recuperar os dados. Alm disso, usaremos a classe SQLiteOpenHelper para gerenciar a conexo 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 mtodos abaixo:

onCreate() Este mtodo chamado quando a conexo com o banco de dados for aberta pela primeira vez. aqui que criaremos o banco de dados, com o comando sql CREATE. onUpdate() Este mtodo chamado quando a verso do banco de dados muda. Por exemplo, digamos que voc criou uma nova verso de seu aplicativo que usa uma tabela a mais no banco de dados. Quando esta nova verso for instalada (em um telefone que j possuir a primeira verso) este mtodo ser chamado, ento voc poder criar apenas a nova tabela, mantendo os dados do usurio.

O cdigo
O cdigo do QuickNotesProvider fica assim, acessando o banco de dados. A seguir, eu explico algumas coisas que podem gerar dvidas.
view plaincopy to clipboardprint?

12

1. package br.com.felipesilveira.quicknotes;
2. 4.

3. import java.util.HashMap; 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. 18.

17. public class QuickNotesProvider extends ContentProvider { 19. 20. 21.


22. // Authority do nosso provider, a ser usado nas Uris. public static final String AUTHORITY = "br.com.felipesilveira.quicknotes.quicknotesprovider"; // Nome do arquivo que ir conter o banco de dados. private static final String DATABASE_NAME = "quicknotes.db"; // Versao do banco de dados. // Este valor importante pois usado em futuros updates do DB. private static final int DATABASE_VERSION = 1;

23. 24.
25.

26. 27. 28.

29.

30. 31.
32.

// Nome da tabela que ir conter as anotaes. private static final String NOTES_TABLE = "notes"; // 'Id' da Uri referente s notas do usurio. private static final int NOTES = 1; // Tag usada para imprimir os logs. public static final String TAG = "QuickNotesProvider"; // Instncia da classe utilitria private DBHelper mHelper; // Uri matcher - usado para extrair informaes das Uris private static final UriMatcher mMatcher; private static HashMap<string, string=""> mProjection; static { mProjection = new HashMap<string, string="">(); mProjection.put(Notes.NOTE_ID, Notes.NOTE_ID); mProjection.put(Notes.TEXT, Notes.TEXT); } static { mMatcher = new UriMatcher(UriMatcher.NO_MATCH); mMatcher.addURI(AUTHORITY, NOTES_TABLE, NOTES); } ///////////////////////////////////////////////////////////////// // Mtodos overrided de ContentProvider // ///////////////////////////////////////////////////////////////// @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = mHelper.getWritableDatabase(); int count; switch (mMatcher.match(uri)) { case NOTES: count = db.delete(NOTES_TABLE, selection, selectionArgs); break; default: throw new IllegalArgumentException( "URI desconhecida " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public String getType(Uri uri) { switch (mMatcher.match(uri)) { case NOTES: return Notes.CONTENT_TYPE; default: throw new IllegalArgumentException(

33. 34.
35.

36. 37.
38.

39. 40.
41.

42. 43.
44. 46.

45. 47. 48. 49. 50. 51.


52.

53. 54. 55. 56.


57.

13

58. 59. 60. 61. 62. 63. 64. 65. 66.


67.

68. 69. 70. 71. 72.


73.

74. 75. 76.


77.

78. 79. 80. 81. 82. 83. 84.

85. 86. 87.


88.

"URI desconhecida " + uri); } }

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); 105. } 106. }
107.

108. 109. 110. 111. 112.


113.

@Override public boolean onCreate() { mHelper = new DBHelper(getContext());; return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Aqui usaremos o SQLiteQueryBuilder para construir // a query que ser feito ao DB, retornando um cursor // que enviaremos aplicao. SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); SQLiteDatabase database = mHelper.getReadableDatabase(); Cursor cursor; switch (mMatcher.match(uri)) { case NOTES: // O Builer receber dois parametros: a tabela // onde ser feita a busca, e uma projection // que nada mais que uma HashMap com os campos // que queremos recuperar do banco de dados. builder.setTables(NOTES_TABLE); builder.setProjectionMap(mProjection); break; default: throw new IllegalArgumentException( "URI desconhecida " + uri); } cursor = builder.query(database, projection, selection, selectionArgs, null, null, sortOrder);

14

114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131.
132.

133. 134. 135. 136.


137. 138.

139.

140.

141. 142. 143.


144.

cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = mHelper.getWritableDatabase(); int count; switch (mMatcher.match(uri)) { case NOTES: count = db.update(NOTES_TABLE, values, selection, selectionArgs); break; default: throw new IllegalArgumentException( "URI desconhecida " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } ///////////////////////////////////////////////////////////////// // Inner Classes utilitrias // ///////////////////////////////////////////////////////////////// public static final class Notes implements BaseColumns { public static final Uri CONTENT_URI = Uri.parse("content://" + QuickNotesProvider.AUTHORITY + "/notes"); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/" + QuickNotesProvider.AUTHORITY; public static final String NOTE_ID = "_id"; public static final String TEXT = "text"; } private static class DBHelper extends SQLiteOpenHelper { DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } /* O mtodo onCreate chamado quando o provider executado pela * primeira vez, e usado para criar as tabelas no database */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + NOTES_TABLE + " (" + Notes.NOTE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + Notes.TEXT + " LONGTEXT" + ");"); } /* O mtodo onUpdate invocado quando a verso do banco de dados

145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158.
159.

160. 161. 162.


163.

164. 165. 166. 167. 168. 169.


170.

15

171. 172.
173. 175.

174. 176. 177.


178. 180.

179. 181. 182. 183.


184.

185. 186. 187. 188. 189. 190. 191. 192. 193.


194.

195.

196. * muda. Assim, usado para fazer adequaes para a aplicao 197. * funcionar corretamente. 198. */ 199. @Override 200. public void onUpgrade(SQLiteDatabase db, 201. int oldVersion, int newVersion) { 202. // Como ainda estamos na primeira verso do DB, 203. // no 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 mtodo query(), e no por acaso: Os cursores so apontadores de dados do banco de dados ou seja, uma interface que permite o acesso aos dados retornados pela query enviada pelo usurio.

notifyChanges()
Em todos os mtodos em que alteramos o banco de dados (inserimos, deletamos ou modificamos dados) importante chamar o mtodo modifyChanges(). Isso far com que as aplicaes que estejam utilizando este conjunto de dados sejam notificadas, permitindo a estas atualizar tambm os dados mostrados ao usurio. No prximo post iremos usar o QuickNotesProvider na nossa aplicao.

16

Acessando um Content Provider


No artigo de hoje comearemos a integrar a nossa aplicao QuickNotes com oQuickNotesProvider, que criamos no artigo anterior. Vamos comear inserindo uma anotao do usurio no banco de dados. Para fazer isso, o primeiro passo adicionar um Listener ao boto Inserir, da seguinte forma:
1.

2. insertButton.setOnClickListener(mInsertListener);

Button insertButton = (Button)findViewById(R.id.insert_button);

E agora, criando o objeto mInsertListener. Ele precisa ser um objeto que implementa a interfaceOnClickListener,. Assim, precisamos implementar o mtodo onClick(), que ser chamado assim que o usurio pressionar o boto.
view plaincopy to clipboardprint?

1. // Definindo um OnClickListener para o boto "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 cdigo acima eu fiz uma chamada a um mtodo que ainda no est implementado o mtodoaddNote(), que recebe um String que ser inserida no banco de dados. Ele ser o mtodo responsvel por efetivamente conversar com o content provider. Vamos implement-lo:
view plaincopy to clipboardprint?

1. 2. 3. 4. 5. 6.
7. 9.

/* * Mtodo responsvel por inserir um registro no content provider */ protected void addNote(String text) { ContentValues values = new ContentValues(); values.put(QuickNotesProvider.Notes.TEXT, text); getContentResolver().insert( QuickNotesProvider.Notes.CONTENT_URI, values);

8. 10. }

Assim, a MainActivity fica dessa forma:


view plaincopy to clipboardprint?

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. 13. 15.

17

12. public class MainActivity extends Activity { 14. 16. 17. 18. 19. 20.
21. private static final String TAG = "QuickNotesMainActivity"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent i = new Intent(this, WelcomeActivity.class); startActivity(i); Button insertButton = (Button)findViewById(R.id.insert_button); insertButton.setOnClickListener(mInsertListener); // adicionando um 'Hint' ao Editbox. EditText editBox = (EditText)findViewById(R.id.edit_box); editBox.setHint("Nova nota..."); } // Definindo um OnClickListener para o boto "Inserir" private OnClickListener mInsertListener = new OnClickListener() { public void onClick(View v) {

22. 23.
24. 25. 27.

26. 28. 29. 30. 31.


32.

33. 34. 35.

36.

37. 38. 39. 40.


41.

EditText editBox = (EditText)findViewById(R.id.edit_box); addNote(editBox.getText().toString()); editBox.setText(""); } }; /* * Mtodo responsvel por inserir um registro no content provider */ protected void addNote(String text) { ContentValues values = new ContentValues(); values.put(QuickNotesProvider.Notes.TEXT, text);

42. 43. 44. 45. 46. 47.


48.

49. getContentResolver().insert( 50. QuickNotesProvider.Notes.CONTENT_URI, values); 51. } 52. }


importante salientar que estamos apenas inserindo o dado no banco de dados no estamos lendo-o em nenhum lugar na nossa aplicao, 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 aplicaes que lidam com banco de dados.

18

Acessando banco de dados atravs do shell


Para acessar o banco de dados pelo shell, iremos iniciar uma sesso com o comando adb shell e ento 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.db SQLite version 3.5.9 Enter .help for instructions sqlite> .schema .schema CREATE 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, ento sinal que o QuickNotesProvider est funcionando corretamente!

Content Providers

Os Content Providers so parte importantssima da arquitetura de um sistema android. responsabilidade deles prover s aplicaes o contedo que elas precisam para funcionar, ou seja, os dados.

Mas por que so realmente necessrios? As aplicaes poderiam muito bem acessar diretamente um banco de dados, por exemplo. Porm, uma boa prtica tornar o modo como os dados so gravados transparente aplicao. Dessa forma, a aplicao pode manter o foco nas interaes com o usurio. Alm disso, essa tcnica permite a criao de Shared Content Providers, que so providers pblicos que podem ser acessados por vrias aplicaes. Por exemplo, existe o content provider de SMS/MMS que permite a qualquer aplicao ler as mensagens recebidas por um telefone celular. E como feita a comunicao entre Content Providers e Aplicaes? Uri. Guarde bem este nome, pois voc ir precisar muito dele durante a sua carreira como desenvolvedor android. Toda a comunicao entre aplicaes e providers feita atravs dos mtodos da interface ContentProvider, que sempre recebem um objeto Uri como parmetro. 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 mtodos 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.

19

O QuickNotes Content Provider

Depois dessa rpida introduo, vamos colocar a mo na massa. Iremos criar um content provider para o QuickNotes, que servir para gravar e recuperar as anotaes do usurio, da seguinte forma:

Intencionalmente coloquei a caixa que define como o provider ir gravar os dados para mostrar que isso irrelevante para a aplicao.

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 parmetros so 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 nmero 10.

20

Criando um Content Provider


Para criar seu prprio content provider, preciso fazer 2 coisas:

1. Criar uma sub-classe da ContentProvider, implementando os mtodos pblicos que eu citei no comeo do artigo; 2. Registrar o provider no AndroidManifest.xml Vamos comear criando a classe QuickNotesProvider:
view plaincopy to clipboardprint?

1. package br.com.felipesilveira.quicknotes;
2.

3. 4. 5. 6.
7.

import import import import

android.content.ContentProvider; android.net.Uri; android.content.ContentValues; android.database.Cursor;

8. public class QuickNotesProvider extends ContentProvider { 9. // Aqui definimos os formatos possveis 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. 15. 16. 17.


18.

@Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public boolean onCreate() { return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; }

19. 20. 21. 22.


23.

24. 25. 26. 27.


28.

29. 30. 31. 32.


33.

34. 35. 36. 37. 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> <provider android:authorities="br.com.felipesilveira.quicknotes.quicknotespro vider" android:name=".QuickNotesProvider"/> E assim o nosso Content Provider est pronto para receber requisies da aplicao. Ainda no retorna nenhum resultado significativo mas isso faremos no prximo artigo, onde ensinarei como acessar um banco de dados SQLite, para fazer esse provider realmente efetivo.

21