Anda di halaman 1dari 267

ANDROID, uma viso geral

Anderson Duarte de Amorim

2011

Contedo
Introduo ....................................................................................................................... 10 Atividades ....................................................................................................................... 11 Criar uma atividade .................................................................................................... 11 Implementando uma interface de usurio ................................................................... 12 Declarando a atividade no manifesto.......................................................................... 13 O uso de filtros inteno ............................................................................................. 13 Iniciar uma atividade .................................................................................................. 14 Iniciar uma atividade para um resultado..................................................................... 15 Encerrar uma atividade ............................................................................................... 16 Gerenciando o ciclo de atividade................................................................................ 16 Aplicar o ciclo de vida callbacks ................................................................................ 17 Salvando estado de atividade ...................................................................................... 23 Manipulao de alteraes na configurao ............................................................... 25 Coordenar as atividades .............................................................................................. 26 Fragmentos ..................................................................................................................... 27 Filosofia de design ...................................................................................................... 27 Criando um fragmento ................................................................................................ 29 DialogFragment ...................................................................................................... 30 ListFragment ........................................................................................................... 31 PreferenceFragment ................................................................................................ 31 Adicionando uma interface de usurio ................................................................... 31 Criando um layout .................................................................................................. 32 Adicionando um fragmento de uma atividade........................................................ 32 Adicionando um fragmento sem uma interface de usurio (UI) ............................ 34 Gerenciando fragmentos ......................................................................................... 35 Executando transaes com fragmento .................................................................. 35

ANDROID, uma viso geral Anderson Duarte de Amorim

Comunicando-se com a atividade ........................................................................... 37 Criar callbacks evento para a atividade .................................................................. 38 Adicionando itens barra de ao .......................................................................... 39 Manuseio do ciclo de vida do fragmento................................................................ 40 Coordenao com o ciclo de vida de atividade ...................................................... 41 Loaders ........................................................................................................................... 43 Resumo API Loader ................................................................................................... 43 Usando carregadores em um aplicativo ...................................................................... 44 Iniciando um Loader ............................................................................................... 45 Reiniciando o Loader.............................................................................................. 46 Usando callbacks do LoaderManager..................................................................... 47 Exemplo ...................................................................................................................... 50 Tarefas e pilha de execuo ............................................................................................ 53 Salvando estado de atividade ...................................................................................... 56 Gerenciando tarefas .................................................................................................... 57 Definio de modos de lanamento ............................................................................ 58 Usando o arquivo de manifesto .................................................................................. 59 Usando as opes de intenes ................................................................................... 61 Manipulao de afinidades ......................................................................................... 62 Limpando a pilha de volta .......................................................................................... 64 Iniciando uma tarefa ................................................................................................... 65 Servios .......................................................................................................................... 66 O bsico ...................................................................................................................... 67 Voc deve utilizar um servio ou um thread? ........................................................ 67 Declarando um servio no manifesto ..................................................................... 69 Criando um servio iniciado ....................................................................................... 70 Segmentao Android 1.6 ou inferior..................................................................... 70

ANDROID, uma viso geral Anderson Duarte de Amorim

Estendendo a classe IntentService .......................................................................... 71 Estendendo a classe de servio ............................................................................... 73 Iniciando um servio .............................................................................................. 77 Parando um servio ................................................................................................ 77 Criando um servio vinculado .................................................................................... 78 Enviando notificaes para o usurio ......................................................................... 79 Executando um servio em primeiro plano ................................................................ 79 Gerenciando ciclo de vida de um servio ................................................................... 80 Aplicando o ciclo de vida dos callbacks ................................................................. 81 Servios vinculados ........................................................................................................ 84 O bsico ...................................................................................................................... 84 Vinculao a um servio iniciado ........................................................................... 84 Criando um servio ligado.......................................................................................... 85 Estendendo a classe Binder .................................................................................... 87 Usando um Messenger ........................................................................................... 90 Vinculao a um servio............................................................................................. 93 Notas adicionais ...................................................................................................... 95 Gerenciando o ciclo de vida de um servio de associao ......................................... 96 Processos e threads ......................................................................................................... 98 Processos .................................................................................................................... 98 Ciclo de vida do processo ....................................................................................... 99 Thread ....................................................................................................................... 102 Threads funcionais ................................................................................................ 103 Usando AsyncTask ............................................................................................... 104 Mtodos de Thread-safe ....................................................................................... 106 Comunicao entre processos ................................................................................... 106 Interface de usurio ...................................................................................................... 108

ANDROID, uma viso geral Anderson Duarte de Amorim

Hierarquia de view.................................................................................................... 108 Como o Android desenha views ........................................................................... 109 Layout ....................................................................................................................... 111 Widgets ..................................................................................................................... 112 Eventos UI ................................................................................................................ 114 Menus ....................................................................................................................... 114 Tpicos Avanados .................................................................................................. 115 Adaptadores .......................................................................................................... 115 Estilos e Temas ..................................................................................................... 116 Declarando Layout ....................................................................................................... 117 Escreve o XML......................................................................................................... 118 Carregar os recursos XML ....................................................................................... 119 Atributos ................................................................................................................... 119 ID .......................................................................................................................... 119 Parmetros de layout ............................................................................................ 120 Posio de Layout ..................................................................................................... 122 Tamanho, padding e margin ..................................................................................... 122 Criando Menus ............................................................................................................. 124 Menu de Opes ................................................................................................... 124 Menu de Contexto ................................................................................................ 124 Submenu ............................................................................................................... 124 Criando um recurso de menu .................................................................................... 124 Inflar um recurso de menu ........................................................................................ 126 Criando um Menu de Opes ................................................................................... 126 Respondendo ao do usurio............................................................................ 127 Alterando os itens de menu em tempo de execuo ............................................. 129 Criando um Menu de Contexto ................................................................................ 129

ANDROID, uma viso geral Anderson Duarte de Amorim

Registre uma ListView ......................................................................................... 130 Criando Submenus.................................................................................................... 132 Outras funes do menu ........................................................................................... 132 Grupos de Menu ................................................................................................... 132 Itens de menu verificados ..................................................................................... 133 As teclas de atalho ................................................................................................ 135 Adicionar intenes em menu dinamicamente ..................................................... 136 Permitindo a sua atividade a ser adicionada para outros menus........................... 137 Usando a barra de ao ................................................................................................. 139 Adicionando a barra de ao .................................................................................... 139 Removendo a barra de ao .................................................................................. 140 Adicionando itens de ao ........................................................................................ 141 Usando o cone do aplicativo como um item de ao .......................................... 142 Usando o cone do aplicativo para navegar "para cima" ...................................... 143 Adicionando uma exibio de ao .......................................................................... 144 Adicionando abas ..................................................................................................... 146 Adicionando de navegao drop-down .................................................................... 149 Exemplo de SpinnerAdapter e OnNavigationListener ......................................... 150 Estilizando a barra de ao ....................................................................................... 152 Criando caixas de dilogo............................................................................................. 156 Mostrando uma caixa de dilogo .............................................................................. 156 Dispensar um dilogo ............................................................................................... 158 Usando demisso de receptores ............................................................................ 158 Criando um AlertDialog ........................................................................................... 159 Adicionando botes .............................................................................................. 160 Adicionando uma lista .......................................................................................... 161 Adicionando caixas de seleo e botes de rdio ................................................. 161

ANDROID, uma viso geral Anderson Duarte de Amorim

Criar um ProgressDialog .......................................................................................... 162 Mostrando uma barra de progresso ...................................................................... 163 Criando uma caixa de dilogo personalizada ........................................................... 166 Manipulando eventos de UI.......................................................................................... 169 Os ouvintes de eventos ............................................................................................. 169 Manipuladores de eventos ........................................................................................ 172 Modo de toque .......................................................................................................... 173 Manipulao do foco ................................................................................................ 174 Notificar o usurio ........................................................................................................ 176 Notificao brinde .................................................................................................... 176 Criando notificaes brinde .................................................................................. 177 Notificao na barra de status................................................................................... 179 Criao de notificaes da barra de status ............................................................ 180 Notificao de dilogo .............................................................................................. 189 Aplicando estilos e temas ............................................................................................. 190 Definio de estilos .................................................................................................. 190 Herana ................................................................................................................. 191 Propriedades do estilo........................................................................................... 192 Aplicando estilos e temas para a interface do usurio .............................................. 194 Aplicar um estilo a uma view ............................................................................... 194 Aplicar um tema a uma atividade ou aplicao .................................................... 195 Selecione um tema baseado na verso de plataforma........................................... 196 Usando estilos e temas da plataforma ...................................................................... 196 Recursos de aplicao ................................................................................................... 198 Armazenamento de dados............................................................................................. 201 Utilizando preferncias compartilhadas ................................................................... 201 Preferncias do usurio ......................................................................................... 202

ANDROID, uma viso geral Anderson Duarte de Amorim

Usando o armazenamento interno ............................................................................ 203 Salvando os arquivos de cache ............................................................................. 204 Usando o armazenamento externo............................................................................ 205 Verificar a disponibilidade dos meios .................................................................. 205 Acessando arquivos em armazenamento externo ................................................. 206 Escondendo seus arquivos a partir da Media Scanner.......................................... 206 Como salvar arquivos que devem ser compartilhados ......................................... 206 Salvando os arquivos de cache ............................................................................. 207 Utilizando bancos de dados ...................................................................................... 208 Banco de dados de depurao ............................................................................... 209 Usando uma conexo de rede ................................................................................... 209 Artigos .......................................................................................................................... 210 Acessibilidade........................................................................................................... 210 Linguagens e recursos .......................................................................................... 210 Linguagens e localidade ....................................................................................... 211 Fazendo o dispositivo falar ................................................................................ 211 Interface .................................................................................................................... 213 Toque .................................................................................................................... 213 Gestos ....................................................................................................................... 216 Mtodo de entrada de dados ................................................................................. 216 Criando um mtodo de entrada de dados ............................................................. 223 Aes de desenhos .................................................................................................... 226 Truques de layout: criando layouts eficientes .......................................................... 229 Truques de layout: usando ViewStub ....................................................................... 234 Truques de layout: mesclando layouts...................................................................... 237 ListView, uma otimizao ........................................................................................ 244 Live folders ............................................................................................................... 247

ANDROID, uma viso geral Anderson Duarte de Amorim

Live Wallpapers ........................................................................................................ 252 Usando webViews .................................................................................................... 254 Funcionalidades ........................................................................................................ 255 Caixa de pesquisa ................................................................................................. 255 Sistema ..................................................................................................................... 258 Alocao de memria ........................................................................................... 258 Zipaling oferece uma otimizao fcil ................................................................. 260 Nota .............................................................................................................................. 263 Fontes ........................................................................................................................... 263 Fontes das imagens ................................................................................................... 266 Fontes dos artigos ..................................................................................................... 266

ANDROID, uma viso geral Anderson Duarte de Amorim

Introduo
O Android um software open-source criado para os celulares e outros dispositivos. O Android Open Source Project (AOSP), liderado pelo Google, est encarregado da manuteno e desenvolvimento do Android. Muitos fabricantes de dispositivos trouxeram ao mercado de dispositivos rodando o Android, e eles so disponveis ao redor do mundo.

O objetivo principal construir uma plataforma de software excelente para usurios de todos os dias. Uma srie de empresas empenhou muitos engenheiros para atingir esse objetivo, e o resultado uma produo total de produtos de consumo de qualidade, cuja fonte aberta para customizao e portabilidade.

Voc pode encontrar mais informaes sobre o Android a partir destas pginas abaixo: Filosofia de projeto e objetivos Interagindo com o projeto Compatibilidade com Android Informaes sobre licenciamento

ANDROID, uma viso geral Anderson Duarte de Amorim

10

Atividades
Uma Activity um componente do aplicativo que fornece uma tela com a qual os usurios podem interagir, a fim de fazer algo, como discar o telefone, tirar uma foto, enviar um e-mail, ou ver um mapa. Para cada atividade dada uma janela na qual se desenha sua interface de usurio. A janela normalmente preenche a tela, mas pode ser menor do que a tela e flutuar em cima de outras janelas. Um aplicativo normalmente consiste de mltiplas atividades que so frouxamente ligadas uns aos outros. Normalmente uma atividade em um aplicativo especificada como a atividade principal", que apresentada ao usurio ao iniciar o aplicativo pela primeira vez. Cada atividade pode comear outra atividade, a fim de executar aes diferentes. Cada vez que comea uma nova atividade, a atividade anterior interrompida, mas o sistema preserva a atividade em uma pilha (a "pilha de volta"). Quando uma nova atividade comea, empurrada para a pilha de volta e leva o foco do usurio. A pilha de volta usa "last in, first out" como mecanismo de fila, ento, quando o usurio est em uma atividade e pressione a tecla BACK, a atividade removida da pilha (e destruda) e retoma a atividade anterior. Quando uma atividade parada por causa de uma nova atividade, h uma notificao da alterao no estado atravs de mtodos de retorno da atividade do ciclo de vida. Existem vrios mtodos de retorno que uma atividade possa receber, devido a uma mudana em seu estado. Por exemplo, quando parado, sua atividade deve liberar todos os objetos grandes, como conexes de rede ou banco de dados. Quando a atividade recomea, voc pode readquirir os recursos necessrios e retomar as aes que foram interrompidas. Estas transies de estado so todos parte do ciclo de atividade.

Criar uma atividade


Para criar uma atividade, voc deve criar uma subclasse da Activity (ou uma subclasse existente do mesmo). Em sua subclasse, voc precisa implementar mtodos de callback que chama o sistema quando ocorrem as transies de atividade entre diversos estados do seu ciclo de vida, como quando a atividade est sendo criada, parou, recomeou, ou foi destruda. Os dois mtodos de retorno mais importantes so: onCreate(): Voc deve implementar este mtodo. O sistema chama isso ao criar a sua atividade. Dentro de sua aplicao, voc deve inicializar os componentes essenciais de ANDROID, uma viso geral Anderson Duarte de Amorim
11

sua atividade. Mais importante, este o lugar onde voc deve chamar setContentView() para definir o layout para a atividade do usurio a interface. onPause(): O sistema chama este mtodo como o primeiro indcio de que o usurio est saindo de sua atividade (embora nem sempre signifique que a atividade est sendo destruda). Isso geralmente onde voc deve cometer quaisquer alteraes que devem ser mantidas para alm da sesso atual do usurio (porque o usurio pode no voltar). Existem vrios mtodos de retorno do ciclo de vida de outros que voc deve usar a fim de proporcionar uma experincia de usurio mais fluida entre as atividades e manipular interrupes inesperadas que causem a sua atividade a ser interrompida e at mesmo destruda.

Implementando uma interface de usurio


A interface de usurio para uma determinada atividade assegurada por uma hierarquia de pontos de vista - objetos derivam da classe View. Cada exibio controla um determinado espao retangular dentro da janela da atividade e pode responder a interao do usurio. Por exemplo, uma viso pode ser um boto que inicia uma ao quando o usurio toc-la. Android fornece um nmero de pontos de vista prontos que voc pode usar para criar e organizar seu layout. "Widgets" so vistas que proporcionam um visual (interativo) de elementos para a tela, como um boto, um campo texto, checkbox, ou apenas uma imagem. "Esquemas" so pontos de vista derivados de ViewGroup que fornecem um modelo de layout exclusivo para a estrutura derivada, como um layout linear, um layout de grade, ou a disposio relativa. Voc pode criar uma subclasse da View e ViewGroup (ou subclasses existentes) para criar seus prprios widgets e layouts e aplic-las ao seu layout atividade. A maneira mais comum para definir um layout usando pontos de vista com um arquivo XML salvo disposio em recursos do seu aplicativo. Dessa forma, voc pode manter o design da sua interface de usurio separadamente do cdigo fonte que define o comportamento da atividade. Voc pode definir o layout da interface do usurio para a sua atividade com setContentView(), passando a identificao do recurso para o layout. No entanto, voc tambm pode criar novas Views no seu cdigo de atividade e construir

ANDROID, uma viso geral Anderson Duarte de Amorim

12

uma hierarquia de vista atravs da insero de novos Views em um ViewGroup, em seguida, usar esse esquema, passando a raiz ViewGroup para setContentView().

Declarando a atividade no manifesto


Voc deve declarar a sua atividade no arquivo de manifesto para que ele seja acessvel para o sistema. Para declarar sua atividade, abra o arquivo e adicione um <activity> como um filho do <application>. Por exemplo:
<manifest ... > <application ... > <activity android:name=".ExampleActivity" /> ... </application ... > ... </manifest >

Existem vrios outros atributos que podem ser includos nesse elemento, para definir propriedades, como o rtulo para a atividade, um cone para a atividade, ou um tema ao estilo de interface do usurio da atividade.

O uso de filtros inteno


Um <activity> tambm pode especificar filtros diferentes, usando o <intent-filter>, a fim de declarar como outros componentes de aplicao podem ativ-lo. Quando voc cria um novo aplicativo usando as ferramentas do Android SDK, a atividade de topo que criada para voc automaticamente inclui a inteno de filtro que declara a atividade e responde ao "principal" e deve ser colocado no "lanador" da categoria. A inteno parece filtro como este:
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>

O elemento <action> especifica que este o "principal ponto de entrada" para o aplicativo. O elemento <category> especifica que esta atividade deve ser listada no sistema lanador de aplicao.

ANDROID, uma viso geral Anderson Duarte de Amorim

13

Se voc pretende que o seu aplicativo seja auto-suficiente e no permita que outras aplicaes ativem as suas atividades, ento voc no precisa de nenhum outro filtro de inteno. Apenas uma atividade deve ter a ao "principal" e "lanador" da categoria, como no exemplo anterior. Atividades que voc no deseja disponibilizar para outros aplicativos no devem ter a inteno de filtros e voc pode inici-los usando as intenes explcitas. No entanto, se voc quiser a sua atividade para responder s intenes implcitas que so entregues a partir de outras aplicaes (e suas prprias), ento voc deve definir filtros de inteno adicional para a sua atividade. Para cada tipo de inteno para o qual pretende responder, voc deve incluir um <intent-filter> que inclui um elemento <action> e, opcionalmente, um elemento <category> e/ou um <data>. Estes elementos especificam o tipo de intenes para que sua atividade possa responder.

Iniciar uma atividade


Voc pode iniciar outra atividade, chamando startActivity(), passando-lhe uma Intent que descreve a atividade que deseja iniciar. A inteno especifica qualquer atividade exatamente o que deseja iniciar ou descreve o tipo de ao que deseja executar (e o sistema seleciona a atividade adequada para voc, que pode mesmo ser de um aplicativo diferente). A inteno tambm pode transportar pequenas quantidades de dados a serem utilizados pela atividade que iniciada. Quando se trabalha dentro de sua prpria aplicao, muitas vezes voc precisa simplesmente lanar uma atividade conhecida. Voc pode fazer isso criando uma inteno que define explicitamente a atividade que deseja iniciar, usando o nome da classe. Por exemplo, aqui est como uma atividade inicia outra atividade denominada SignInActivity:
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);

No entanto, sua aplicao pode tambm querer executar alguma ao, como enviar um e-mail, mensagem de texto, ou atualizao de status, usando dados de sua atividade. Neste caso, sua aplicao no pode ter as suas prprias atividades para realizar tais aes, para que voc possa aproveitar ao invs das atividades previstas por outras aplicaes no dispositivo, que pode executar as aes para voc. Este o lugar onde as

ANDROID, uma viso geral Anderson Duarte de Amorim

14

intenes so realmente valiosas, voc pode criar uma inteno que descreve uma ao que deseja executar e o sistema inicia a atividade adequada a partir de outro aplicativo. Se houver mltiplas atividades que podem manipular a inteno, ento o usurio pode selecionar qual usar. Por exemplo, se voc quer permitir que o usurio envie uma mensagem de e-mail, voc pode criar a seguinte inteno:
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);

O EXTRA_EMAIL extra adicionado uma matriz de seqncia de endereos de e-mail para onde o e-mail deve ser enviado. Quando um aplicativo de e-mail responde a esta inteno, ele l a matriz de cadeia prevista na extra e as coloca no campo "Para" do formulrio de composio de e-mail.

Iniciar uma atividade para um resultado


s vezes, voc pode querer receber um resultado da atividade que voc comear. Nesse caso, iniciar a atividade, chamando startActivityForResult() (em vez de startActivity() ). Para ento receber o resultado da atividade subseqente, aplicar o onActivityResult(), mtodo de retorno. Quando a atividade subseqente feita, ele retorna um resultado de uma Intent para o seu mtodo onActivityResult(). Por exemplo, talvez voc queira que o usurio escolha um de seus contatos, para que sua atividade pode fazer algo com as informaes desse contato. Veja como voc pode criar uma inteno e manipular o resultado:
private void pickContact() { // Create an intent to "pick" a contact, as defined by the content provider URI Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT_REQUEST); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // If the request went well (OK) and the request was PICK_CONTACT_REQUEST if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { // Perform a query to the contact's content provider for the contact's name Cursor cursor = getContentResolver().query(data.getData(), new String[] {Contacts.DISPLAY_NAME}, null, null, null); if (cursor.moveToFirst()) { // True if the cursor is not empty int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); String name = cursor.getString(columnIndex);

ANDROID, uma viso geral Anderson Duarte de Amorim

15

// Do something with the selected contact's name... } } }

Este exemplo mostra a lgica bsica que voc deve usar seu mtodo onActivityResult() para lidar com um resultado de atividade. A primeira condio verifica se a solicitao foi bem-sucedida, se for, ento o resultCode ser RESULT_OK e se a solicitao para que este resultado est respondendo conhecido, neste caso, o requestCode coincide com o segundo parmetro enviada com startActivityForResult(). De l, o cdigo manipula o resultado de atividade, consultando os dados retornados de uma Intent. O que acontece , um ContentResolver executa uma consulta contra um provedor de contedo, que retorna um Cursor que permite que os dados consultados possam serem lidos.

Encerrar uma atividade


Voc pode encerrar uma atividade chamando seu mtodo finish(). Voc tambm pode encerrar uma atividade separada que j comeou chamando finishActivity() . Nota: Na maioria dos casos, voc no deve terminar explicitamente uma atividade com estes mtodos. Como discutido na seo seguinte sobre o ciclo de vida de atividade, o sistema Android gerencia a vida de uma atividade para voc, ento voc no precisa terminar a sua prpria atividade. Chamar esses mtodos pode afetar negativamente a experincia do usurio e s deve ser usado quando voc realmente no quer que o usurio retorne a esta instncia da atividade.

Gerenciando o ciclo de atividade


Gerenciar o ciclo de vida de suas atividades atravs da implementao de mtodos de retorno essencial para desenvolver uma aplicao forte e flexvel. O ciclo de vida de uma atividade est diretamente afetada pela sua associao com outras atividades, a sua misso e voltar pilha. Uma atividade pode existir em trs estados, essencialmente: Retomado: A atividade est em primeiro plano da tela e tem o foco do usurio. (Esse estado tambm por vezes referido como "run".)

ANDROID, uma viso geral Anderson Duarte de Amorim

16

Em pausa: Outra atividade est em primeiro plano e tem foco, mas este ainda visvel. Ou seja, outra atividade visvel na parte superior de um presente e que a atividade parcialmente transparente ou no cobre a tela inteira. Uma atividade em pausa est completamente viva (o objeto Activity mantido na memria, ele mantm todas as informaes do estado e membro, e permanece preso ao gerenciador de janelas), mas pode ser morta pelo sistema em situaes de pouca memria. Parado: A atividade totalmente obscurecida por outra atividade (a atividade est agora em "background"). A atividade parada tambm est ainda viva (o objeto Activity mantido na memria, ele mantm todas as informaes do estado e membro, mas no est ligado ao gerenciador de janelas). No entanto, j no visvel para o usurio e pode ser morto pelo sistema quando a memria necessria em outro lugar. Se uma atividade est em pausa ou parada, o sistema pode retir-la da memria, quer por pedir para terminar (chamando seu finish()), ou simplesmente matar o processo. Quando a atividade aberta novamente (depois de ter sido concludo ou morto), ela deve ser criada por toda parte.

Aplicar o ciclo de vida callbacks


Quando uma atividade transita entrando e saindo dos diferentes estados descritos acima, ele notificado atravs de vrios mtodos de retorno. Todos os mtodos de callback so ganchos que voc pode substituir para fazer um trabalho adequado quando o estado da sua atividade muda. A atividade seguinte inclui cada um dos mtodos de ciclo de vida fundamentais:
public class ExampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // The activity is being created. } @Override protected void onStart() { super.onStart(); // The activity is about to become visible. } @Override protected void onResume() { super.onResume(); // The activity has become visible (it is now "resumed"). }

ANDROID, uma viso geral Anderson Duarte de Amorim

17

@Override protected void onPause() { super.onPause(); // Another activity is taking focus (this activity is about to be "paused"). } @Override protected void onStop() { super.onStop(); // The activity is no longer visible (it is now "stopped") } @Override protected void onDestroy() { super.onDestroy(); // The activity is about to be destroyed. } }

Nota: A implementao destes mtodos do ciclo de vida deve sempre chamar a implementao da superclasse antes de fazer qualquer trabalho, conforme mostrado nos exemplos acima. Juntos, esses mtodos definem o ciclo de vida de uma atividade. Ao implementar esses mtodos, voc pode monitorar trs loops aninhados no ciclo de vida de atividade: A vida inteira de uma atividade acontece entre a chamada para onCreate() e a chamada para onDestroy(). Sua atividade deve executar a instalao do "Estado" global (tal como a definio de layout) em onCreate(), e liberar todos os recursos remanescentes em onDestroy(). Por exemplo, se a sua atividade tem um

segmento em execuo em segundo plano para transferir os dados da rede, ele pode criar esse tpico em onCreate() e depois parar o segmento em onDestroy(). O tempo de vida visvel de uma atividade acontece entre a chamada para onStart() e a chamada para onStop(). Durante este tempo, o usurio pode ver a atividade na tela e interagir com ele. Por exemplo, onStop() chamado quando inicia uma nova atividade e esta no mais visvel. Entre estes dois mtodos, voc pode manter os recursos que so necessrios para mostrar a atividade para o usurio. Por exemplo, voc pode registrar um BroadcastReceiver em onStart() para monitorar as mudanas que impactam sua interface do usurio, e cancelar o registro em onStop() quando o usurio no pode mais ver o que voc est sendo exibido. O sistema pode chamar onStart() e onStop() vrias vezes durante toda a vida til da atividade, como a atividade se alterna entre visvel e oculta para o usurio. ANDROID, uma viso geral Anderson Duarte de Amorim

18

O tempo de vida do primeiro plano de uma atividade acontece entre a chamada para onResume() e a chamada para onPause(). Durante este tempo, a atividade est na frente de todas as outras atividades na tela e tem foco de entrada do usurio. Uma atividade pode freqentemente transitar para dentro e fora do plano, por exemplo, onPause() chamado quando o dispositivo vai dormir ou quando uma caixa de dilogo aparece. O cdigo desses dois mtodos deve ser bastante leve, para evitar transies lentas que fazem o usurio esperar. A figura 1 ilustra esses laos e os caminhos de uma atividade que podem levar a esses estados.

Figura 1. O ciclo de vida de atividade.

ANDROID, uma viso geral Anderson Duarte de Amorim

19

Tabela 1. Um resumo do ciclo de vida do callback mtodos atividade.

Mtodo

Descrio Chamado quando a atividade criada pela primeira vez. Isto onde voc deve fazer tudo do seu conjunto esttico

Killable depois?

Seguinte

onCreate()

normal - criar pontos de vista, vincular dados em listas, e assim por diante. Sempre seguido por onStart() . Chamado atividade depois foi que a

No

onStart()

interrompida, No onStart()

onRestart()

pouco antes de ele ser iniciado novamente. Sempre seguido por onStart() Chamado imediatamente antes da atividade tornar-se visvel para o usurio. Seguido por

onStart()

onResume() se a atividade vem para o primeiro plano, ou onStop() se torna oculto. Chamado imediatamente antes da atividade passar a interagir com o usurio. Neste ponto, a

No

onResume()

onResume()

atividade est no topo da pilha de atividade. Sempre seguido por onPause() .

No

onPause()

ANDROID, uma viso geral Anderson Duarte de Amorim

20

Chamado quando o sistema est prestes a comear a retomar a outra atividade. Este mtodo geralmente usado para confirmar as alteraes no salvas, dados persistentes, animaes stop e outras coisas que podem estar consumindo onPause() CPU, e assim por diante. Ele deve fazer tudo o que ele faz muito rapidamente, porque a prxima atividade no ser retomada at que ele retorne. Seguidas por onResume() se a atividade retorna para a frente, ou por onStop() se torna invisvel para o usurio. Chamado quando a atividade j no visvel para o usurio. Isso pode acontecer porque ele est sendo destrudo, ou porque outra atividade (seja um existente ou uma nova) foi onStop() retomado e est cobrindo-o. Seguidas por onRestart() se a atividade est voltando para interagir com o usurio, ou por onDestroy() se essa Sim onRestart() ou onDestroy() Sim onResume() ou onStop()

atividade est indo embora.

ANDROID, uma viso geral Anderson Duarte de Amorim

21

Chamado

antes

que

atividade destruda. Esta a chamada final que a atividade ir receber.Poderia quer est chamado porque ser a

chamada, atividade onDestroy() (algum

acabando finish() Sim nada

nela), ou porque o sistema est destruindo essa instncia da atividade para economizar espao. Voc pode distinguir entre estes dois cenrios com o isFinishing().

A coluna chamada "killable depois?" indica se o sistema pode matar o processo que acolhe a atividade a qualquer momento aps o mtodo retornar, sem executar outra linha. Trs mtodos so marcados como "sim": (onPause() , onStop() , e onDestroy() ). onPause() o primeiro dos trs, uma vez que a atividade criada, onPause() o ltimo mtodo que garantido para ser chamado antes que o processo pode ser morto, se o sistema deve recuperar a memria em caso de emergncia, ento onStop() e onDestroy() no podem ser chamados. Portanto, voc deve usar onPause() para escrever dados persistentes para armazenamento. No entanto, voc deve ser seletivo sobre quais informaes devem ser mantidas durante onPause(), porque os procedimentos de bloqueio neste mtodo bloqueiam a passagem para a prxima atividade e retardam a experincia do usurio. Mtodos que so marcados como "No" na coluna killable protegem o processo da atividade de ser morto desde o momento em que so chamados. Assim, uma atividade killable a partir do momento onPause() e retorna quando onResume() chamado. No ser novamente killable at onPause() seja novamente chamado e retornado. Nota: uma atividade que no tecnicamente "killable" por esta definio na tabela 1 ainda pode ser morta pelo sistema, mas isso vai acontecer apenas em circunstncias extremas, quando no h outro recurso.

ANDROID, uma viso geral Anderson Duarte de Amorim

22

Salvando estado de atividade


A introduo Gesto do Ciclo de Atividade menciona brevemente que, quando uma atividade est em pausa ou parada, o estado da atividade mantido. Isto verdade porque a Activity ainda est retida na memria quando est em pausa ou parada, todas as informaes sobre seus membros e estado atuais ainda esto vivos. Assim, qualquer alterao que o usurio fez no mbito da atividade retida na memria, de modo que quando a atividade retorna para o primeiro plano (quando ele "retoma"), essas mudanas ainda esto l.

Figura 2. As duas formas em que para a atividade um usurio retorna ao foco com seu estado intacto, quer a atividade interrompida, e retomada em seguida, o estado de atividade permanece intacta ( esquerda), ou a atividade destrudo, ento recriada e a atividade deve restaurar o estado da atividade anterior (direita).

No entanto, quando o sistema destri uma atividade, a fim de recuperar a memria, a Activity destruda, ento o sistema no pode simplesmente continuar com o seu estado intacto. Em vez disso, o sistema deve recriar a Activity se o usurio navega de volta para ele. No entanto, o usurio no sabe que o sistema destri e recria a atividade e, assim, provavelmente espera que a atividade seja exatamente como era. Nessa situao,

ANDROID, uma viso geral Anderson Duarte de Amorim

23

voc pode garantir que informaes importantes sobre o estado de atividade so preservadas atravs da implementao de um mtodo de retorno adicional que permite que voc salve as informaes sobre o estado de sua atividade e, em seguida, restaura quando o sistema recria a atividade. O mtodo de callback em que voc pode salvar informaes sobre o estado atual da sua atividade onSaveInstanceState(). O sistema chama este mtodo antes de fazer a atividade vulnervel a ser destruda e passa-lhe um objeto Bundle. O Bundle o lugar onde voc pode armazenar informaes de estado sobre a atividade como pares valornome, utilizando mtodos como putString(). Ento, se o sistema mata a atividade e o usurio navega de volta para sua atividade, o sistema passa o Bundle para onCreate() para que voc possa restaurar o estado de atividade que tenha sido guardado durante onSaveInstanceState(). Se no h informaes do estado para restaurar, em seguida, o Bundle que passou a onCreate() se torna nulo. Nota: No h nenhuma garantia de que onSaveInstanceState() ser chamado antes de sua atividade ser destruda, porque h casos em que no ser necessrio salvar o estado (como quando o usurio deixa a sua atividade com a chave de volta, porque a usurio explicitamente encerra as atividades). Se o mtodo for chamado, ele sempre chamado antes de onStop() e, possivelmente, antes de onPause(). No entanto, mesmo se voc no faz nada e no implementar onSaveInstanceState(), alguns estados de atividade so restaurados pela Activity de implementao padro da classe de onSaveInstanceState(). Especificamente, a implementao padro chama onSaveInstanceState() para cada View no layout, que permite fornecer informaes sobre si que devem ser salvos. Quase todos os widgets no mbito Android implementam este mtodo, de modo que qualquer mudana visvel para o interface do usurio so automaticamente salvas e restauradas quando sua atividade recriada. Por exemplo, o EditText salva qualquer texto digitado pelo usurio e o CheckBox widget salva se marcado ou no. O nico trabalho exigido por voc fornecer uma identificao nica (com o android:id) para cada elemento grfico que deseja salvar seu estado. Se um elemento no tem um ID, ento ele no pode salvar seu estado. Voc tambm pode parar explicitamente de salvar em seu layout seu estado, definindo o android:saveEnabled para "false" ou chamando o setSaveEnabled(). Normalmente, voc

ANDROID, uma viso geral Anderson Duarte de Amorim

24

no deve desativar isso, mas voc pode caso queira restaurar o estado da atividade de interface diferente. Embora a implementao padro de onSaveInstanceState() salva as informaes teis sobre a atividade da sua interface, voc ainda pode precisar substitu-lo para guardar informaes adicionais. Por exemplo, voc talvez precise salvar valores de um membro que mudou na vida da atividade (que poderiam se correlacionar com os valores restaurados na interface do usurio, mas os membros que detm esses valores UI no so restaurados, por padro). Como a implementao padro de onSaveInstanceState() ajuda a salvar o estado da interface do usurio, se voc substituir o mtodo para salvar informaes de estado adicionais, voc deve sempre chamar a implementao da superclasse de onSaveInstanceState() antes de fazer qualquer trabalho. Nota: Devido ao onSaveInstanceState() no ser garantido de ser chamado, voc deve us-lo apenas para registrar o estado transiente da atividade (o estado da interface do usurio), voc nunca deve us-lo para armazenar dados persistentes. Em vez disso, voc deve usar onPause() para armazenar dados persistentes (como os dados que devem ser salvos em um banco de dados) quando o usurio deixa a atividade. Uma boa maneira de testar a capacidade do seu aplicativo para restaurar seu estado simplesmente girar o dispositivo para fazer alteraes na orientao da tela. Quando da mudana de orientao da tela, o sistema destri e recria a atividade a fim de aplicar recursos alternativos que possam estar disponveis para a nova orientao. Por esta razo, muito importante para sua atividade restaurar completamente o seu estado quando ele recriado, pois os usurios regularmente giram a tela ao usar aplicaes.

Manipulao de alteraes na configurao


Algumas configuraes de dispositivo podem mudar durante a execuo (tais como a orientao da tela, a disponibilidade de teclado e idioma). Quando essa mudana ocorre, o Android reinicia a atividade em execuo (onDestroy() chamado, seguido imediatamente por onCreate()). O comportamento reiniciar projetado para ajudar a sua candidatura a se adaptar s novas configuraes automaticamente recarregando a sua aplicao com recursos alternativos que voc forneceu. Se voc projeta sua atividade

ANDROID, uma viso geral Anderson Duarte de Amorim

25

para lidar adequadamente com este evento, vai ser mais resistentes a eventos inesperados no ciclo de atividade. A melhor maneira de lidar com uma mudana de configurao, tais como uma mudana na orientao da tela, simplesmente preservar o estado do seu aplicativo usando onSaveInstanceState() e onRestoreInstanceState() (ou onCreate() ), como discutido na seo anterior.

Coordenar as atividades
Quando uma atividade comea outra, ambas experimentam as transies do ciclo de vida. A primeira atividade faz uma pausa e para (embora, no vai parar se ele ainda est visvel ao fundo), enquanto a outra atividade criada. Caso esses dados compartilham atividades salvas em disco ou em outro lugar, importante entender que a primeira atividade no est completamente parada antes de a segunda ser criada. Pelo contrrio, o processo de iniciar o segundo se sobrepe ao processo de parar o primeiro. A ordem dos retornos do ciclo de vida bem definida, especialmente quando as duas atividades esto no mesmo processo e est comeando um do outro. Aqui est a ordem das operaes que ocorrem quando a atividade A comea atividade B: 1. O mtodo onPause() da atividade A executado. 2. Os mtodos onCreate(), onStart(), e onResume() de B so executados em seqncia. (Atividade B agora tem o foco do usurio.) 3. Ento, se uma atividade no mais visvel na tela, a sua onStop() executada. Esta seqncia previsvel de callbacks do ciclo de vida permite-lhe gerir a transio de informaes de uma atividade para outra. Por exemplo, se voc deve escrever em um banco de dados quando a primeira atividade pra para que esta atividade pode l-lo, ento voc deve escrever para o banco de dados durante onPause() em vez de durante onStop().

ANDROID, uma viso geral Anderson Duarte de Amorim

26

Fragmentos
Um Fragment representa um comportamento ou uma parte da interface de usurio em uma Activity. Voc pode combinar vrios fragmentos em uma nica atividade para construir uma interface multi-painel e reutilizao de um fragmento de atividades mltiplas. Voc pode pensar em um fragmento como uma seo modular de uma atividade, que tem seu prprio ciclo de vida, recebe os seus prprios eventos de entrada, e que voc pode adicionar ou remover, enquanto a atividade est em execuo. Um fragmento deve sempre ser incorporado em uma atividade e o ciclo de vida do fragmento diretamente afetado pelo ciclo de vida da atividade de acolhimento. Por exemplo, quando a atividade interrompida, assim so todos os fragmentos nele, e quando a atividade destruda, assim so todos os fragmentos. No entanto, enquanto uma atividade est em execuo (que na retomada do ciclo de vida do estado), voc pode manipular cada fragmento de forma independente, como adicionar ou remover. Quando voc executa uma operao deste tipo de fragmento, voc tambm pode adicion-la a uma pilha de volta que gerenciado pela atividade de cada pilha de volta na entrada da atividade que um registro da transao de fragmento que ocorreu. A volta da pilha permite que o usurio possa reverter uma transao (navegar para trs), pressionando a tecla BACK. Quando voc adiciona um fragmento como uma parte do seu layout, ele vive em um ViewGroup dentro da view de hierarquia e define o seu prprio layout de pontos de vista. Voc pode inserir um fragmento em seu layout declarando o fragmento na atividade de distribuio de arquivos, como <fragment>, ou a partir de seu cdigo de aplicativo, adicionando-o a um j existente ViewGroup. No entanto, um fragmento no obrigado a fazer parte do esquema de atividade, voc tambm pode utilizar um fragmento como um trabalhador invisvel para a atividade.

Filosofia de design
Android apresenta fragmentos no Android 3.0 (API Level "Honeycomb"), principalmente para apoiar projetos mais dinmicos e flexveis de interface do usurio em telas grandes, como os Tablets. Como uma tela de tablet muito maior do que a de um telefone, h mais espao para combinar e trocar os componentes de interface do usurio. Fragmentos permitem tais projetos sem a necessidade de gerenciar mudanas

ANDROID, uma viso geral Anderson Duarte de Amorim

27

complexas hierarquia vista. Ao dividir o layout de uma atividade em fragmentos, voc se torna capaz de modificar a aparncia da atividade em tempo de execuo e preservar essas mudanas em uma pilha de volta que gerenciada pela atividade. Por exemplo, um aplicativo de notcias pode usar um fragmento para mostrar uma lista de artigos esquerda e outro fragmento para mostrar um artigo direita, ento os fragmentos aparecem em uma atividade, lado a lado, e cada fragmento tem seu prprio conjunto do ciclo de vida, mtodos callback e lidam com seus prprios eventos de entrada do usurio. Assim, em vez de usar uma atividade para selecionar um artigo e outra atividade para ler o artigo, o usurio pode selecionar um artigo e ler tudo dentro da mesma atividade, conforme ilustrado na figura 1.

Figura 1. Um exemplo de como dois mdulos de interface do usurio que normalmente so separados em duas atividades podem ser combinados em uma atividade, utilizando fragmentos.

Um fragmento deve ser um componente modular e reutilizvel em sua aplicao. Ou seja, porque o fragmento define o seu prprio layout e seu prprio comportamento, usando seu prprio ciclo de vida callbacks, voc pode incluir um fragmento em mltiplas atividades. Isto especialmente importante porque permite adaptar a sua experincia de usurio para diferentes tamanhos de tela. Por exemplo, voc pode incluir vrios fragmentos de uma atividade apenas quando o tamanho da tela suficientemente grande, e, quando no , lanar atividades distintas que utilizam diferentes fragmentos. Por exemplo, para continuar com o aplicativo de notcia, a aplicao pode inserir dois fragmentos da atividade, quando rodando em uma grande tela extra (um tablet, por exemplo). No entanto, em um tamanho de tela normal (um telefone, por exemplo), no h lugar suficiente para os dois fragmentos, de modo a Atividade A inclui somente o fragmento para a lista de artigos, e quando o usurio seleciona um artigo, ele comea a

ANDROID, uma viso geral Anderson Duarte de Amorim

28

Atividade B, que inclui o fragmento para ler o artigo. Assim, a aplicao suporta os padres de projeto sugerido na figura 1.

Criando um fragmento

Figura 2. O ciclo de vida de um fragmento (enquanto a sua atividade est em execuo).

ANDROID, uma viso geral Anderson Duarte de Amorim

29

Para criar um fragmento, voc deve criar uma subclasse de Fragment (ou uma subclasse existente do mesmo). O cdigo da classe Fragment se parece muito com uma Activity. Ele contm mtodos de retorno semelhante a uma atividade, como onCreate(), onStart(), onPause(), e onStop(). Na verdade, se voc est convertendo uma aplicao Android existentes para usar fragmentos, voc pode simplesmente mover o cdigo de mtodos de retorno de sua atividade sobre os mtodos de retorno de seus respectivos fragmentos. Normalmente, voc deve implementar pelo menos os mtodos do ciclo de vida a seguir: onCreate(): O sistema chama isso ao criar o fragmento. Dentro de sua aplicao, voc deve inicializar os componentes essenciais do fragmento que pretende manter quando o fragmento pausado ou parado, ento retomado. onCreateView(): O sistema chama isso quando est na hora de extrair o fragmento de sua interface de usurio pela primeira vez. Para desenhar uma interface para o seu fragmento, voc deve retornar um View a partir deste mtodo que a raiz do fragmento do seu layout. Voc pode retornar nulo se o fragmento no fornece uma interface do usurio. onPause(): O sistema chama este mtodo como o primeiro indcio de que o usurio est saindo do fragmento (embora nem sempre significa que o fragmento est sendo destrudo). Isso geralmente onde voc deve cometer quaisquer alteraes que devem ser mantidas para alm da sesso atual do usurio (porque o usurio pode no voltar). A maioria dos aplicativos devem implementar pelo menos estes trs mtodos para cada fragmento, mas existem vrios mtodos de retorno que voc tambm deve usar para lidar com diferentes fases do ciclo de vida do fragmento. Todos os mtodos de retorno do ciclo de vida so discutidos mais adiante, na seo sobre o manuseio do Ciclo de Vida do fragmento. Existem tambm algumas subclasses que voc pode querer estender:

DialogFragment
Mostra uma janela flutuante. Usar essa classe para criar uma caixa de dilogo uma boa alternativa para usar os mtodos auxiliares de dilogo na Activity, porque voc pode incorporar um fragmento de dilogo para a volta da pilha de fragmentos gerido pela atividade, permitindo que o usurio retorne a um fragmento rejeitado. ANDROID, uma viso geral Anderson Duarte de Amorim

30

ListFragment
Exibe uma lista de itens que so gerenciados por um adaptador (como um SimpleCursorAdapter), semelhante ao ListActivity. Ele fornece diversos mtodos para gerenciar uma lista, como o onListItemClick() de callback para manipular eventos de clique.

PreferenceFragment
Exibe uma hierarquia de objetos Preference como uma lista, semelhante PreferenceActivity. Isso til quando se cria um "settings" para sua aplicao.

Adicionando uma interface de usurio


Um fragmento normalmente usado como parte de uma atividade de interface de usurio e contribui com a sua prpria disposio para a atividade. Para fornecer um layout de um fragmento, voc deve implementar o onCreateView(), que o sistema Android chama quando hora do fragmento ser desenhado no layout. A implementao deste mtodo deve retornar um View que a raiz do fragmento do seu layout. Nota: Se o fragmento uma subclasse de ListFragment, a implementao padro retorna um ListView de onCreateView(), ento voc no precisa implement-lo. Para devolver um layout de onCreateView(), voc pode retir-lo a partir de um layout de recursos definidos em XML e o desenvolve. Para ajud-lo a faz-lo, onCreateView() fornece um LayoutInflater objeto. Por exemplo, aqui est uma subclasse de Fragment que carrega um layout a partir da example_fragment.xml:
public static class ExampleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container, false); } }

ANDROID, uma viso geral Anderson Duarte de Amorim

31

Criando um layout
No exemplo acima, R.layout.example_fragment uma referncia a um recurso chamado layout example_fragment.xml salvo na aplicao dos recursos. O parmetro passado para onCreateView() o pai ViewGroup (da atividade do layout), em que o layout do fragmento ser inserido. O parmetro savedInstanceState um Bundle que fornece dados sobre a instncia anterior do fragmento, se o fragmento est sendo retomado. O mtodo inflate() utiliza trs argumentos: A identificao de recurso do layout que voc deseja inserir. O ViewGroup ser o pai do layout j em utilizao. Passando o container importante para que o sistema possa aplicar os parmetros de layout para o modo de exibio raiz do layout inflado, especificado pela posio do pai em que ele est indo. Um booleano que indica se o layout desenvolvido dever ser anexado ao ViewGroup (segundo parmetro) durante a chamada do procedimento inflate(). (Neste caso, isso falso, porque o sistema j est inserindo o layout inflado no container de passagem verdade seria criar um grupo de vista redundantes no layout final.)

Adicionando um fragmento de uma atividade


Normalmente, um fragmento contribui com uma parcela de UI para a atividade de acolhimento, que incorporado como parte da hierarquia da viso da atividade de conjunto. H duas maneiras com as quais voc pode adicionar um fragmento para o layout de atividade: Declare o fragmento dentro atividade de layout do arquivo. Neste caso, voc pode especificar propriedades de layout para o fragmento como se fosse uma exibio. Por exemplo, aqui est o arquivo de layout para uma atividade com dois fragmentos:

ANDROID, uma viso geral Anderson Duarte de Amorim

32

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.example.news.ArticleListFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.news.ArticleReaderFragment" android:id="@+id/viewer" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>

O atributo android:name na <fragment> especifica o Fragment para instanciar no layout. Quando o sistema cria esse layout, ele instancia cada fragmento especificado no layout e chama o onCreateView() para cada um, para recuperar o layout de cada fragmento. O sistema insere a View retornada pelo fragmento diretamente no local do elemento <fragment>. Nota: Cada fragmento requer um identificador nico que o sistema pode usar para restaurar o fragmento se a atividade for reiniciada (e que voc pode usar para capturar o fragmento para realizar transaes, como remov-lo). Existem trs formas para fornecer uma identificao de um fragmento:
o o o

Fornea o android:id com um ID nico. Fornea o android:tag com uma string nica. Se voc no fornecer nenhum dos dois anteriores, o sistema utiliza a identificao de exibio de recipiente.

Ou ento, programaticamente adicionar o fragmento de um j existente ViewGroup . A qualquer momento, enquanto sua atividade est sendo executada, voc pode adicionar fragmentos ao seu layout. Voc s precisa especificar um ViewGroup para colocar o fragmento.

ANDROID, uma viso geral Anderson Duarte de Amorim

33

Para fazer transaes em sua atividade (como adicionar, remover ou substituir um fragmento), voc deve usar as APIs do FragmentTransaction. Voc pode obter uma instncia de FragmentTransaction de sua Activity como esta:
FragmentManager fragmentManager = getFragmentManager() FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Voc pode ento adicionar um fragmento ao usar o mtodo add(), especificando o fragmento a adicionar e a viso para inseri-lo. Por exemplo:
ExampleFragment fragment = new ExampleFragment(); fragmentTransaction.add(R.id.fragment_container, fragment); fragmentTransaction.commit();

O primeiro argumento passado para add() o ViewGroup em que o fragmento deve ser colocado, especificado por identificao do recurso, e o segundo parmetro o fragmento a acrescentar. Depois que voc fizer as alteraes com FragmentTransaction , voc deve chamar commit() para que as alteraes tenham efeito.

Adicionando um fragmento sem uma interface de usurio (UI)


Os exemplos acima mostram como adicionar um fragmento de sua atividade, a fim de fornecer uma interface do usurio. No entanto, voc tambm pode usar um fragmento para fornecer um comportamento de fundo para a atividade sem a apresentao da interface do usurio. Para adicionar um fragmento sem uma interface de usurio, adicione o fragmento da atividade usando add(Fragment, String) (fornecimento de uma nica seqncia de "tag" para o fragmento, ao invs de um ID). Isso adiciona o fragmento, mas, porque no est associada a um ponto de vista do layout atividade, ele no recebe uma chamada para onCreateView(). Assim voc no precisa implementar esse mtodo. Fornecendo uma tag string para o fragmento no estritamente para os fragmentos noUI. Voc tambm pode fornecer etiquetas de seqncia de fragmentos que possuem uma interface de usurio, mas se o fragmento no possui uma interface de usurio, a tag string o nico caminho para identific-lo. Se voc deseja obter o fragmento da atividade posterior, voc precisa usar findFragmentByTag().

ANDROID, uma viso geral Anderson Duarte de Amorim

34

Gerenciando fragmentos
Para gerenciar os fragmentos em sua atividade, voc precisar usar FragmentManager. Para obt-lo, chame getFragmentManager() em sua atividade. Algumas coisas que voc pode fazer com FragmentManager incluem: Obter fragmentos que existem na atividade, com findFragmentById() (para os fragmentos que fornecem uma interface de usurio no layout de atividade) ou findFragmentByTag() (para os fragmentos que fazem ou no uma interface do usurio). Retirar fragmentos da pilha, com popBackStack() (simulando um comando BACK pelo usurio). Registre-se um ouvinte de alterao de parte de trs da pilha, com addOnBackStackChangedListener(). Conforme demonstrado na seo anterior, voc tambm pode usar FragmentManager para abrir uma FragmentTransaction, que lhe permite realizar transaes, tais como adicionar e remover fragmentos.

Executando transaes com fragmento


Uma das grandes novidades sobre o uso de fragmentos em sua atividade a capacidade de adicionar, remover, substituir e realizar outras aes com eles, em resposta interao do usurio. Cada conjunto de alteraes que comprometem a atividade chamado de transao e voc pode executar um usando APIs em FragmentTransaction. Voc tambm pode salvar cada transao na pilha gerenciada pela atividade, permitindo ao usurio navegar para trs atravs das mudanas no fragmento (semelhante ao navegar para trs por meio de atividades). Voc pode adquirir uma instncia de FragmentTransaction do FragmentManager como este:
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Cada transao um conjunto de mudanas que se deseja realizar, ao mesmo tempo. Voc pode configurar todas as alteraes que pretendem efetuar uma operao

ANDROID, uma viso geral Anderson Duarte de Amorim

35

determinada utilizando mtodos como add(), remove(), e replace(). Em seguida, para aplicar a operao para a atividade, voc deve chamar commit(). Antes de chamar commit(), no entanto, voc pode querer chamar addToBackStack(), a fim de acrescentar a operao a uma volta da pilha de transaes. Esta volta na pilha gerida pela atividade e permite que ao usurio retornar ao estado de fragmento anterior, pressionando a tecla BACK. Por exemplo, aqui est como voc pode substituir um fragmento a outro e preservar o estado anterior da pilha de volta:
// Create new fragment and transaction Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit();

Neste exemplo, newFragment substitui qualquer fragmento (se houver) atualmente no continer de layout identificado pelo R.id.fragment_container ID. Ao chamar addToBackStack(), salvado na pilha de volta a operao para que o usurio possa anular a operao e trazer de volta o fragmento anterior pressionando a tecla BACK. Se voc adicionar vrias alteraes operao (como um outro add() ou remove()) e chamar addToBackStack(), ento todas as mudanas aplicadas antes de chamar commit() so adicionados volta da pilha como uma nica operao e a tecla BACK ir inverter-los todos juntos. A ordem na qual voc adiciona as alteraes em um FragmentTransaction no importa, exceto: Voc deve chamar commit() por ltimo. Se voc est adicionando vrios fragmentos para o mesmo recipiente, ento a ordem em que voc adicion-los determina a ordem em que aparecem na hierarquia.

ANDROID, uma viso geral Anderson Duarte de Amorim

36

Se voc no chamar addToBackStack() quando voc executar uma operao que remove um fragmento, em seguida, esse fragmento destrudo quando a transao for confirmada e o usurio no pode navegar de volta para ela. Considerando que, se voc chamar addToBackStack() quando da remoo de um fragmento, o fragmento interrompido e ser retomado se o usurio navega de volta. Dica: Para cada transao, voc pode aplicar uma animao de transio, chamando setTransition() antes do commit(). Chamar commit() no executa a operao imediatamente. Em vez disso, ele agenda a execuo no segmento da atividade de interface do usurio (a thread "main"), logo que o segmento for capaz de faz-lo. Se necessrio, no entanto, voc pode chamar executePendingTransactions() no seu segmento de interface do usurio para executar imediatamente as operaes apresentadas por commit(). Fazer isso geralmente no necessrio a menos que a transao uma dependncia para o emprego em outros segmentos. Cuidado: voc pode cometer uma transao usando commit() apenas antes da atividade salvar seu estado (quando o usurio deixa a atividade). Se a tentativa for cometer depois desse ponto, uma exceo ser lanada. Isso ocorre porque o estado, aps a confirmao, pode ser perdido se a atividade precisa ser restaurada. Para as situaes em que no tem problema voc perder o commit, use

commitAllowingStateLoss().

Comunicando-se com a atividade


Ainda que um Fragment seja implementado como um objeto que independente de uma Activity e pode ser usado dentro de mltiplas atividades, uma determinada instncia de um fragmento est diretamente ligada atividade que o contm. Especificamente, o fragmento pode acessar a instncia Activity com getActivity() e facilmente realizar tarefas como encontrar um ponto de vista do esquema de atuao:
View listView = getActivity().findViewById(R.id.list);

Da mesma forma, sua atividade pode chamar mtodos no fragmento atravs da aquisio de uma referncia para o Fragment de FragmentManager, usando findFragmentById() ou findFragmentByTag(). Por exemplo:

ANDROID, uma viso geral Anderson Duarte de Amorim

37

ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

Criar callbacks evento para a atividade


Em alguns casos, voc pode precisar de um fragmento de compartilhar eventos com a atividade. Uma boa maneira de fazer isso definir uma interface de retorno no interior do fragmento e exigem que a atividade de acolhimento implemente-a. Quando a atividade recebe uma chamada atravs da interface, ela pode compartilhar a informao com outros fragmentos no layout conforme necessrio. Por exemplo, se um aplicativo de notcias tem dois fragmentos de uma atividade e um mostra uma lista de artigos (fragmento A) e outro mostra um artigo (fragmento B), ento um fragmento deve informar a atividade quando um item da lista escolhido de modo que pode dizer ao fragmento B para exibir o artigo. Neste caso, a interface OnArticleSelectedListener declarada dentro de um fragmento:
public static class FragmentA extends ListFragment { ... // Container Activity must implement this interface public interface OnArticleSelectedListener { public void onArticleSelected(Uri articleUri); } ... }

Em

seguida,

atividade

que

hospeda

fragmento

implementa

OnArticleSelectedListener e substitui onArticleSelected() para notificar o fragmento B do evento a partir do fragmento A. Para garantir que a atividade de acolhimento implemente essa interface, um fragmento do mtodo onAttach() de retorno (que chama o sistema quando adicionando o fragmento para a atividade) instancia uma instncia de OnArticleSelectedListener pelo casting da Activity que passado para onAttach():
public static class FragmentA extends ListFragment { OnArticleSelectedListener mListener; ... @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnArticleSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); }

ANDROID, uma viso geral Anderson Duarte de Amorim

38

} ... }

Se a atividade no tenha aplicado a interface, ento o fragmento lana um ClassCastException. Em caso de sucesso, o membro mListener mantm uma referncia para a implementao da atividade de OnArticleSelectedListener, de modo que um fragmento pode compartilhar eventos com a atividade, chamando os mtodos definidos pela interface OnArticleSelectedListener. Por exemplo, se um fragmento uma extenso do ListFragment, cada vez que o usurio clica em um item da lista, o sistema chama onListItemClick() no fragmento, o que chama onArticleSelected() para compartilhar o evento com a atividade:
public static class FragmentA extends ListFragment { OnArticleSelectedListener mListener; ... @Override public void onListItemClick(ListView l, View v, int position, long id) { // Append the clicked item's row ID with the content provider Uri Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id); // Send the event and Uri to the host activity mListener.onArticleSelected(noteUri); } ... }

O parmetro id passado para onListItemClick() o ID da linha do item clicado, que a atividade (ou outro fragmento) utiliza para buscar o artigo a partir do aplicativo ContentProvider.

Adicionando itens barra de ao


Seus fragmentos podem contribuir itens de menu para a atividade do menu de opes (e, conseqentemente, a Barra de ao) pela execuo onCreateOptionsMenu(). Para que esse mtodo receba chamadas, no entanto, voc deve chamar setHasOptionsMenu() durante onCreate(), para indicar que o fragmento gostaria de adicionar itens ao menu de opes (caso contrrio, o fragmento no ir receber uma chamada para onCreateOptionsMenu()). Os itens que voc adicionar ao menu de opes do fragmento so acrescentados aos itens de menu existente. O fragmento tambm recebe callbacks para

onOptionsItemSelected() quando um item de menu selecionado.

ANDROID, uma viso geral Anderson Duarte de Amorim

39

Voc tambm pode registrar uma exibio em seu layout para fornecer um menu de contexto, chamando registerForContextMenu(). Quando o usurio abre o menu de contexto, o fragmento recebe uma chamada para onCreateContextMenu(). Quando o usurio seleciona um item, o fragmento recebe uma chamada para

onContextItemSelected(). Nota: Embora o fragmento receba um on-item-selected na chamada de retorno para cada item de menu que acrescenta, a atividade a primeira a receber o respectivo retorno quando o usurio seleciona um item de menu. Se a execuo da atividade da chamada de retorno no item selecionado no lidar com o item selecionado, o evento transmitido para retorno do fragmento. Isso verdadeiro para o menu de opes e menus de contexto.

Manuseio do ciclo de vida do fragmento

Figura 3. O ciclo de vida afeta a atividade do ciclo de vida do fragmento.

ANDROID, uma viso geral Anderson Duarte de Amorim

40

Gerenciar o ciclo de vida de um fragmento um pouco como gerir o ciclo de vida de uma atividade. Como uma atividade, um fragmento pode existir em trs estados: Retomado: O fragmento visvel na atividade de execuo. Em pausa: Outra atividade est em primeiro plano e tem o foco, mas a atividade em que vive esse fragmento ainda visvel (a atividade do primeiro plano parcialmente transparente ou no cobre a tela inteira). Parado: O fragmento no visvel. A atividade host foi parada ou o fragmento foi retirado da atividade, mas adicionado volta da pilha. Um fragmento que parou ainda est vivo (todas as informaes do estado e membro so mantidas pelo sistema). No entanto, j no visvel para o usurio e sero mortos se a atividade morta. Tambm como uma atividade, voc pode manter o estado de um fragmento com um Bundle, no caso de a atividade do processo ser morta e voc precisar restaurar o estado do fragmento, quando a atividade recriada. Voc pode salvar o estado durante o fragmento onSaveInstanceState() de callback e restaur-lo durante onCreate(), onCreateView() ou onActivityCreated(). A diferena mais significativa no ciclo de vida entre uma atividade e um fragmento como so armazenados em suas respectivas pilhas. Uma atividade colocada em uma pilha de volta das atividades que gerido pelo sistema quando ela est parada, por padro (para que o usurio possa navegar de volta a ele com a chave de volta, como discutido em Tarefas e pilha de volta). No entanto, um fragmento colocado em uma pilha de volta gerido pela atividade de acolhimento somente quando voc solicitar explicitamente que a instncia deve ser salva chamando addToBackStack() durante uma operao que remove o fragmento. Gerenciar o ciclo de vida do fragmento muito semelhante gesto do ciclo de vida da atividade. Assim, as mesmas prticas de gesto do ciclo de vida de atividade tambm se aplicam aos fragmentos. O que voc tambm precisa entender, porm, como a vida da atividade afeta a vida do fragmento.

Coordenao com o ciclo de vida de atividade


O ciclo de vida da atividade em que o fragmento de vida afeta diretamente o ciclo de vida do fragmento, da mesma forma que cada ciclo de retorno para a atividade resulta ANDROID, uma viso geral Anderson Duarte de Amorim

41

em um retorno semelhante para cada fragmento. Por exemplo, quando a atividade recebe onPause(), cada fragmento na atividade recebe onPause(). Fragmentos tm alguns retornos do ciclo de vida extra, no entanto, para lidar com uma interao nica com a atividade, a fim de realizar aes como construir e destruir UI do fragmento. Estes mtodos de callback adicionais so: onAttach(): Chamado quando o fragmento foi associado com a atividade. onCreateView(): Chamado para criar a hierarquia de viso associada com o fragmento. onActivityCreated(): Chamado quando onCreate() da atividade foi retornado. onDestroyView(): Chamado quando a hierarquia de viso associada com o fragmento est sendo removida. onDetach(): Chamado quando o fragmento est sendo dissociado da atividade. O fluxo do ciclo de vida de um fragmento, como ele afetado por sua atividade de acolhimento, ilustrado pela figura 3. Nesta figura, voc pode ver o que cada estado sucessivo da atividade que determina os mtodos de retorno de um fragmento pode receber. Por exemplo, quando a atividade tenha recebido uma onCreate() de callback, um fragmento da atividade no recebe mais do que o onActivityCreated() de callback. Uma vez que a atividade atinge o estado retomado, voc pode adicionar livremente e remover fragmentos na a atividade. Assim, somente quando a atividade est em estado de retomada, o ciclo de vida de um fragmento pode mudar de forma independente. No entanto, quando a atividade deixa o estado de retomada, o fragmento novamente inserido atravs do ciclo de vida da atividade.

ANDROID, uma viso geral Anderson Duarte de Amorim

42

Loaders
Loaders tornam fcil carregar os dados de forma assncrona, em uma atividade ou um fragmento. Loaders tm estas caractersticas: Eles esto disponveis para cada Activity e Fragment. Eles fornecem carga assncrona de dados. Eles monitoram a fonte de seus dados e entregam novos resultados quando muda o contedo. Eles reconectam automaticamente o cursor do gestor passado, quando est sendo recriado aps uma mudana de configurao. Assim, eles no precisam de voltar a consultar os seus dados.

Resumo API Loader


Existem vrias classes e interfaces que podem ser envolvidos na utilizao de carregadores em um aplicativo. Os resultados esto resumidos nesta tabela: Classe/Interface LoaderManager Descrio Uma classe abstrata associada a uma Activity ou Fragment para gerenciar uma ou mais instncias Loader. Isso ajuda a gerenciar um pedido de execuo de operaes j em conjunto com o ciclo de vida de Activity ou Fragment, o uso mais comum deste com um CursorLoader, no entanto as aplicaes so livres para escrever seus prprios loaders para carregar outros tipos de dados. H apenas um LoaderManager por atividade ou fragmento. Mas um LoaderManager pode ter vrios carregadores. LoaderManager.LoaderCallbacks Uma interface de retorno de um cliente para interagir com o LoaderManager. Por exemplo, voc usar o onCreateLoader() para criar um carregador novo.

ANDROID, uma viso geral Anderson Duarte de Amorim

43

Loader

Uma classe abstrata que executa o carregamento assncrono de dados. Esta a classe base para um gestor. Voc usaria normalmente CursorLoader, mas voc pode implementar sua prpria subclasse. Enquanto os carregadores esto ativos, eles devem acompanhar a fonte de seus dados e apresentar resultados novos quando alterar o contedo.

AsyncTaskLoader

Carregador abstrato que prov AsyncTansk para o trabalho.

CursorLoader

Uma subclasse de AsyncTaskLoader que consulta o ContentResolver e retorna um Cursor. Essa classe implementa o protocolo Loader de uma forma padro para consultar cursores, com base em AsyncTaskLoader para realizar a consulta de cursor em uma discusso de fundo para que ele no bloqueie os aplicativo de interface do usurio. Utilizar este carregador a melhor maneira de carregar os dados de forma assncrona a partir de um ContentProvider, ao invs de realizar uma consulta gerida atravs do fragmento ou de APIs.

As classes e interfaces na tabela acima so os componentes essenciais que voc vai usar para implementar um carregador em sua aplicao. Voc no vai precisar de todos eles para cada gestor, mas voc sempre precisa de uma referncia ao LoaderManager para inicializar um carregador e uma implementao de um Loader, como CursorLoader. As sees a seguir mostram como usar essas classes e interfaces em uma aplicao.

Usando carregadores em um aplicativo


Um aplicativo que usa carregadores normalmente inclui o seguinte: Uma Activity ou Fragment. Uma instncia da LoaderManager.

ANDROID, uma viso geral Anderson Duarte de Amorim

44

Um CursorLoader para carregar dados apoiado por uma ContentProvider. Alternativamente, voc pode implementar sua prpria subclasse de Loader ou AsyncTaskLoader para carregar dados de alguma outra fonte. Uma implementao para LoaderManager.LoaderCallbacks. Isto onde voc cria novos loaders e gerencia suas referncias aos carregadores existentes. Uma maneira de mostrar o carregador de dados, como um

SimpleCursorAdapter. Uma fonte de dados, como um ContentProvider, ao usar um CursorLoader .

Iniciando um Loader
O LoaderManager gerencia um ou mais instncias Loader dentro de uma Activity ou Fragment. H apenas um LoaderManager por atividade ou fragmento. Normalmente, voc inicializa um Loader com o mtodo onCreate() dentro da atividade ou mtodo onActivityCreated() dentro do fragmento. Voc pode fazer isso da seguinte forma:
// Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this);

O mtodo initLoader() utiliza os seguintes parmetros: Um ID exclusivo que identifica o carregador. Neste exemplo, a identificao 0. Os argumentos opcionais para fornecer ao loader a construo (null neste exemplo). A execuo de LoaderManager.LoaderCallbacks, em que a LoaderManager chamada para relatar eventos carregador. Neste exemplo, a classe local implementa a interface LoaderManager.LoaderCallbacks, assim que passa uma referncia para si, this.

ANDROID, uma viso geral Anderson Duarte de Amorim

45

A chamada ao initLoader() assegura que um carregador inicializado e ativo. Ele tem dois resultados possveis: Se o carregador especificado pelo ID j existe, o ltimo carregador criado reutilizado. Se o carregador especificado pela ID no existir, initLoader() aciona o mtodo LoaderManager.LoaderCallbacks em onCreateLoader(). Isto onde voc implementa o cdigo para instanciar e retornar um carregador novo. Em ambos os casos, a aplicao determinada LoaderManager.LoaderCallbacks est associada com o carregador, e ser chamada quando o estado muda carregador. Se no momento da chamada, o chamador est em seu estado inicial e o carregador solicitado j existe e tem gerado os seus dados, o sistema solicita onLoadFinished() (durante initLoader()), ento voc deve estar preparado para isso acontecer. Observe que o mtodo initLoader() retorna o Loader que criado, mas voc no precisa capturar uma referncia a ele. O LoaderManager gerencia a vida do carregador automaticamente. O LoaderManager inicia e pra de carregar quando necessrio, e mantm o estado do carregador e do seu contedo associado. Isso implica que voc raramente interage com carregadores diretamente. mais comumente usar o LoaderManager.LoaderCallbacks para intervir no processo de carregamento quando ocorrem eventos especficos.

Reiniciando o Loader
Quando voc usa initLoader(), como mostrado acima, ele usa um carregador existente com a identificao especificada, se houver. Se no houver, ele cria um. Mas s vezes voc deseja descartar os dados antigos e comear de novo. Para descartar os dados antigos, use restartLoader(). Por exemplo, essa implementao de SearchView.OnQueryTextListener reinicia o carregador quando o usurio muda de consulta. O loader precisa ser reiniciado para que ele possa usar a pesquisa de reviso de filtro para fazer uma nova consulta:

ANDROID, uma viso geral Anderson Duarte de Amorim

46

public boolean onQueryTextChanged(String newText) { // Called when the action bar search text has changed. Update // the search filter, and restart the loader to do a new query // with this filter. mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; getLoaderManager().restartLoader(0, null, this); return true; }

Usando callbacks do LoaderManager


LoaderManager.LoaderCallbacks uma interface de callback que permite que um cliente interaja com o LoaderManager . Loaders, em especial o CursorLoader, so esperados para reter seus dados depois de ser interrompido. Isso permite aos aplicativos que mantenham seus dados atravs dos mtodos onStop() e onStart() da atividade ou fragmento, de modo que quando os usurios retornam a um pedido, eles no tem que aguardar os dados para recarregarem. Voc usa o mtodo LoaderManager.LoaderCallbacks quando quer saber quando criar um carregador novo, e para dizer a aplicao quando hora de parar de usar um gerenciador de dados. LoaderManager.LoaderCallbacks inclui os seguintes mtodos: onCreateLoader() - instancia e retorna um novo Loader para o ID dado. onLoadFinished() - Chamado quando um loader criado anteriormente terminou sua carga. onLoaderReset() - Chamado quando um loader criado anteriormente est sendo redefinido, tornando os dados disponveis. Esses mtodos so descritos em detalhes nas sees seguintes. onCreateLoader Quando voc tenta acessar um loader (por exemplo, atravs initLoader()), ele verifica se o carregador especificado pelo ID existe. Se isso no ocorrer, ele aciona o mtodo onCreateLoader() do LoaderManager.LoaderCallbacks. Isto onde voc ir criar um carregador novo. Normalmente, esse ser um CursorLoader, mas voc pode implementar sua prpria subclasse Loader.

ANDROID, uma viso geral Anderson Duarte de Amorim

47

Neste exemplo, o onCreateLoader() cria um mtodo de retorno CursorLoader. Voc deve construir o CursorLoader usando o mtodo construtor, que exige um conjunto completo de informaes necessrias para realizar uma consulta para o

ContentProvider. Especificamente, necessrio: URI - A URI para o contedo para recuperar. projeo - uma lista de quais colunas retornar. Passando null ir retornar todas as colunas, que ineficiente. seleo - Um filtro que declara que as linhas de retorno, formatado como uma clusula WHERE SQL (excluindo o prprio WHERE). Passando null retornar todas as linhas para o URI especificado. selectionArgs - Voc pode incluir ?s na seleo, que sero substitudas pelos valores da selectionArgs, na ordem em que aparecem na seleo. Os valores sero vinculados como Strings. SortOrder - Como adquirir as linhas, formatado como uma clusula ORDER BY de SQL (excluindo-se o ORDER BY). Passando null usar a ordem de classificao padro, que pode ser desordenada.
// If non-null, this is the current filter the user has provided. String mCurFilter; ... public Loader<Cursor> onCreateLoader(int id, Bundle args) { // This is called when a new Loader needs to be created. This // sample only has one Loader, so we don't care about the ID. // First, pick the base URI to use depending on whether we are // currently filtering. Uri baseUri; if (mCurFilter != null) { baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(mCurFilter)); } else { baseUri = Contacts.CONTENT_URI; } // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))"; return new CursorLoader(getActivity(), baseUri, CONTACTS_SUMMARY_PROJECTION, select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); }

ANDROID, uma viso geral Anderson Duarte de Amorim

48

onLoadFinished Este mtodo chamado quando um loader criado anteriormente terminou sua carga. Este mtodo garantido para ser chamado antes do lanamento do ltimo dado que foi fornecido para este carregador. Neste ponto, voc deve remover todo uso dos dados antigos (desde que ser lanado em breve), mas no deve fazer a seu prprio lanamento dos dados desde o seu carregador o dono e vai cuidar disso. O carregador vai lanar os dados, uma vez que conhece que o aplicativo no est mais usando. Por exemplo, se os dados so um cursor de um CursorLoader, voc no deve chamar close() sobre ele mesmo. Se o cursor est sendo colocado em um CursorAdapter, voc deve usar o mtodo swapCursor() para que o antigo Cursor no seja fechado. Por exemplo:
// This is the Adapter being used to display the list's data. SimpleCursorAdapter mAdapter; ... public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data); }

onLoaderReset Este mtodo chamado quando um loader criado anteriormente est sendo redefinido, tornando os seus dados indisponveis. Este retorno permite saber quando o dado est prestes a ser liberado assim voc pode remover a referncia a ele. Esta aplicao chama swapCursor() com um valor null:
// This is the Adapter being used to display the list's data. SimpleCursorAdapter mAdapter; ... public void onLoaderReset(Loader<Cursor> loader) { // This is called when the last Cursor provided to onLoadFinished() // above is about to be closed. We need to make sure we are no // longer using it. mAdapter.swapCursor(null); }

ANDROID, uma viso geral Anderson Duarte de Amorim

49

Exemplo
Como exemplo, aqui a implementao completa de um Fragment que apresenta um ListView com os resultados de uma consulta contra o provedor de contedo contatos. Ele usa um CursorLoader para gerenciar a consulta do fornecedor. Para uma aplicao para acessar os contatos de um usurio, como mostrado neste exemplo, o manifesto deve incluir a permisso READ_CONTACTS .
public static class CursorLoaderListFragment extends ListFragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> { // This is the Adapter being used to display the list's data. SimpleCursorAdapter mAdapter; // If non-null, this is the current filter the user has provided. String mCurFilter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Give some text to display if there is no data. In a real // application this would come from a resource. setEmptyText("No phone numbers"); // We have a menu item to show in action bar. setHasOptionsMenu(true); // Create an empty adapter we will use to display the loaded data. mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_2, null, new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS }, new int[] { android.R.id.text1, android.R.id.text2 }, 0); setListAdapter(mAdapter); // Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // Place an action bar item for searching. MenuItem item = menu.add("Search"); item.setIcon(android.R.drawable.ic_menu_search); item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); SearchView sv = new SearchView(getActivity()); sv.setOnQueryTextListener(this); item.setActionView(sv); } public boolean onQueryTextChange(String newText) {

ANDROID, uma viso geral Anderson Duarte de Amorim

50

// Called when the action bar search text has changed. Update // the search filter, and restart the loader to do a new query // with this filter. mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; getLoaderManager().restartLoader(0, null, this); return true; } @Override public boolean onQueryTextSubmit(String query) { // Don't care about this. return true; } @Override public void onListItemClick(ListView l, View v, int position, long id) { // Insert desired behavior here. Log.i("FragmentComplexList", "Item clicked: " + id); } // These are the Contacts rows that we will retrieve. static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS, Contacts.CONTACT_PRESENCE, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY, }; public Loader<Cursor> onCreateLoader(int id, Bundle args) { // This is called when a new Loader needs to be created. This // sample only has one Loader, so we don't care about the ID. // First, pick the base URI to use depending on whether we are // currently filtering. Uri baseUri; if (mCurFilter != null) { baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(mCurFilter)); } else { baseUri = Contacts.CONTENT_URI; } // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))"; return new CursorLoader(getActivity(), baseUri, CONTACTS_SUMMARY_PROJECTION, select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); } public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data); }

ANDROID, uma viso geral Anderson Duarte de Amorim

51

public void onLoaderReset(Loader<Cursor> loader) { // This is called when the last Cursor provided to onLoadFinished() // above is about to be closed. We need to make sure we are no // longer using it. mAdapter.swapCursor(null); } }

ANDROID, uma viso geral Anderson Duarte de Amorim

52

Tarefas e pilha de execuo


Um aplicativo normalmente contm vrias atividades. Cada atividade deve ser concebida em torno de um tipo especfico de ao que o usurio pode realizar e pode iniciar outras atividades. Por exemplo, um aplicativo de e-mail pode ter uma atividade para mostrar uma lista de e-mail. Quando o usurio seleciona um e-mail, uma nova atividade aberta para ver o e-mail. Uma atividade pode at iniciar atividades que existem em outras aplicaes no dispositivo. Por exemplo, se sua aplicao quer enviar um e-mail, voc pode definir a inteno de realizar um "send" e incluir alguns dados, tais como um endereo de e-mail e uma mensagem. Uma atividade de outra aplicao que se declara para lidar com este tipo de inteno, em seguida, aberta. Neste caso, a inteno enviar um e-mail, assim a atividade de "compor" e-mail comea (se mltiplas atividades apiam a mesma inteno, ento o sistema permite ao usurio selecionar qual usar). Quando o email enviado, sua atividade retomada e parece como se a atividade de e-mail parte do seu aplicativo. Mesmo que as atividades podem ser de diferentes aplicaes, o Android mantm essa experincia do usurio uniforme, mantendo as duas atividades na mesma tarefa. Uma tarefa um conjunto de atividades que os usurios interagem ao realizar um determinado trabalho. As atividades so organizadas em uma pilha (a "pilha de volta"), na ordem em que cada atividade aberta. A tela inicial o ponto de partida para a maioria das tarefas. Quando o usurio toca num cone na tela do aplicativo (ou um atalho na tela inicial), essa tarefa vem para o primeiro plano. Se existe uma tarefa para a aplicao (o pedido no tenha sido usado recentemente), ento uma nova tarefa criada e a atividade "principal" abre como a atividade da raiz na pilha. Quando a atividade atual comea outra, a nova atividade empurrada na parte superior da pilha e ganha foco. A atividade anterior permanece na pilha, mas est parada. Quando uma atividade termina, o sistema mantm o estado atual de sua interface de usurio. Quando o usurio pressiona a tecla BACK, a atividade atual retirada da parte superior da pilha (a atividade destruda) e a atividade anterior recomea (o estado anterior de sua interface restaurado). Atividades na pilha nunca so reorganizadas, s ANDROID, uma viso geral Anderson Duarte de Amorim

53

includas e excludas da pilha - inseridas na pilha quando iniciado pela atividade atual e retiradas quando o usurio deixa-as usando a tecla BACK. Como tal, a parte de trs da pilha funciona como uma estrutura de objetos "last in, first out". A Figura 1 mostra esse comportamento com uma linha do tempo mostrando o progresso entre as atividades junto com a atual pilha de volta em cada momento.

Figura 1. Uma representao de como cada nova atividade em uma tarefa adiciona um item na parte de trs da pilha. Quando o usurio pressiona a tecla BACK, a atividade atual destruda e volta atividade anterior.

Se o usurio continuar a pressionar BACK, ento cada atividade da pilha retirada para revelar a anterior, at que o usurio retorna tela inicial (ou de qualquer atividade que estava sendo executada quando a tarefa comeou). Quando todas as atividades so removidas da pilha, a tarefa no existe mais.

Figura 2. Duas tarefas tarefa esto no fundo, esperando para ser retomado, enquanto a Tarefa B recebe interao do usurio em primeiro plano.

ANDROID, uma viso geral Anderson Duarte de Amorim

54

Figura 3. A nica atividade instanciada vrias vezes.

Uma tarefa uma unidade coesa, que pode passar para o "background" quando os usurios comeam uma nova tarefa ou vo para a tela inicial, atravs da tecla HOME. Enquanto no fundo, todas as atividades na tarefa esto paradas, mas a pilha de volta para a tarefa permanece intacta, a tarefa simplesmente perdeu o foco enquanto outra tarefa se realiza como mostrado na figura 2. Uma tarefa pode, em seguida, voltar ao "primeiro plano" para que os usurios possam continuar de onde pararam. Suponha, por exemplo, que a tarefa atual (Tarefa A) tenha trs atividades em sua pilha e dois no mbito da atividade corrente. O usurio pressiona a tecla HOME, e em seguida, inicia uma nova aplicao a partir do lanador de aplicao. Quando a tela inicial aparece, uma tarefa vai para o fundo. Quando inicia o novo aplicativo, o sistema inicia uma tarefa para a aplicao (Tarefa B) com sua prpria pilha de atividades. Aps a interao com esse aplicativo, o usurio volta para HOME novamente e seleciona o aplicativo que originalmente comeou Tarefa A. Agora, a tarefa A vem para o primeiro plano - todas as trs atividades em sua pilha esto intactas e as atividades no topo da pilha so retomadas. Neste ponto, o usurio tambm pode voltar Tarefa B indo para a HOME e selecionando o cone do aplicativo que iniciou essa tarefa (ou tocando e segurando a tecla HOME para revelar as tarefas recentes e selecionando uma). Este um exemplo de multitarefa no Android. Nota: Vrias tarefas podem ser realizadas no fundo de uma vez. No entanto, se o usurio estiver executando muitas tarefas em segundo plano ao mesmo tempo, o sistema pode comear a destruir as atividades do fundo, a fim de recuperar a memria, fazendo com que os estados de atividade possam ser perdidos. Como as atividades na parte de trs da pilha nunca so reorganizadas, se seu aplicativo permite que usurios iniciem uma atividade especfica de mais de uma atividade, uma

ANDROID, uma viso geral Anderson Duarte de Amorim

55

nova instncia daquela atividade criada e colocada na pilha (ao invs de trazer qualquer instncia anterior da atividade para o topo). Como tal, uma atividade em seu aplicativo pode ser instanciada vrias vezes (mesmo de diferentes tarefas), como mostrado na figura 3. Como tal, se o usurio navega para trs usando a tecla BACK, cada instncia da atividade revelada na ordem em que foi aberta (cada um com seu estado prprio de UI). No entanto, voc pode modificar esse comportamento se voc no quer uma atividade a ser instanciada mais de uma vez. Para resumir o comportamento padro de atividades e tarefas: Quando a atividade A comea atividade B, uma atividade interrompida, mas o sistema mantm o seu estado (como a posio de rolagem e texto inseridos em formulrios). Se o usurio pressiona a tecla de volta, enquanto na Atividade B, a atividade A continua com o seu estado restaurado. Quando o usurio deixa uma tarefa, pressionando a tecla HOME, a atividade em curso interrompida e sua tarefa vai para o fundo. O sistema mantm o estado de cada atividade na tarefa. Se o usurio depois recomea a tarefa de selecionar o cone do lanador, que comeou a tarefa, ela vem para o primeiro plano e retoma a atividade no topo da pilha. Se o usurio pressionar a tecla BACK, a atividade atual removida da pilha e destruda. A atividade anterior na pilha retomada. Quando uma atividade destruda, o sistema no mantm atividade do Estado. As atividades podem ser instanciadas vrias vezes, at mesmo de outras tarefas.

Salvando estado de atividade


Como discutido acima, o comportamento padro do sistema preserva o estado de uma atividade quando est parada. Desta forma, quando os usurios navegam de volta para uma atividade anterior, sua interface parece do jeito que deixou. No entanto, voc pode, e deve, de forma proativa manter o estado de suas atividades atravs de mtodos de retorno, caso a atividade seja destruda e deve ser recriada. Quando o sistema pra uma de suas atividades (como quando inicia uma nova atividade ou movimenta as tarefas para o fundo), o sistema poderia destruir completamente essa atividade se ele precisa recuperar a memria do sistema. Quando isso acontece, as

ANDROID, uma viso geral Anderson Duarte de Amorim

56

informaes sobre o estado da atividade so perdidas. Se isso acontecer, o sistema ainda sabe que a atividade tem um lugar na parte de trs da pilha, mas quando a atividade trazida para o topo da pilha, o sistema deve recri-la (em vez de retom-la). A fim de evitar a perda do trabalho do usurio, voc deve mant-la de forma proativa atravs da aplicao do mtodo onSaveInstanceState() de retorno de sua atividade.

Gerenciando tarefas
A forma como o Android gerencia as tarefas e a pilha de volta, como descrito acima colocando todas as atividades que comearam sucessivamente na mesma tarefa e em uma pilha "last in, first out" - funciona muito bem para a maioria das aplicaes e voc no deve se preocupar em como suas atividades esto associadas a tarefas ou como eles existem na parte de trs da pilha. No entanto, voc pode decidir que voc deseja interromper o comportamento normal. Talvez voc queira uma atividade em seu aplicativo para iniciar uma nova tarefa quando iniciada (em vez de ser colocada dentro da tarefa atual), ou, quando voc comea uma atividade, que pretende apresentar uma instncia existente da mesma (em vez de criar uma nova instncia no topo da pilha de volta), ou, voc quer a sua pilha para ser limpas de todas as activitiesstart, com exceo para a atividade de raiz quando o usurio deixa a tarefa. Voc pode fazer essas coisas e mais, com atributos no manifesto da <activity> e com bandeiras de inteno que voc passa para startActivity(). Neste sentido, os principais atributos de <activity> que voc pode usar so: taskAffinity launchMode allowTaskReparenting clearTaskOnLaunch alwaysRetainTaskState finishOnTaskLaunch E as principais bandeiras de inteno voc pode usar so: FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_SINGLE_TOP ANDROID, uma viso geral Anderson Duarte de Amorim

57

Ateno: A maioria dos aplicativos no deve interromper o comportamento padro de atividades e tarefas. Se voc determinar que seja necessrio para a sua atividade modificar o comportamento padro, tenha cuidado e no se esquea de testar a usabilidade da atividade durante o lanamento e quando se navega de volta a ele de outras atividades e tarefas com a tecla BACK. Certifique-se de teste para os comportamentos de navegao que possam ser incompatveis com o comportamento esperado do usurio.

Definio de modos de lanamento


Modos de Lanamento permitem que a definir como uma nova instncia de uma atividade est associada tarefa atual. Voc pode definir diferentes modos de lanamento de duas maneiras: Usando o arquivo de manifesto o Quando voc declarar uma atividade em seu arquivo de manifesto, voc pode especificar como a atividade deve se associar com as tarefas quando iniciada. Usando as opes de Intenes o Quando voc chamar startActivity(), voc pode incluir uma bandeira na Intent que declara como (ou se) a nova atividade deve associar com a tarefa atual. Como tal, se a atividade A inicia a atividade B, a atividade B pode definir no seu manifesto de como ele deve se associar com a tarefa atual (caso exista) e uma atividade tambm pode pedir o quanto a atividade B deve associar com a tarefa atual. Se ambas as atividades definem como a atividade B deve associar com uma tarefa, ento a solicitao da atividade A (como definido na inteno) honrada sobre o pedido da atividade B (como definido no seu manifesto). Nota: Alguns dos modos disponveis no lanamento do manifesto no esto disponveis como sinalizadores para uma inteno e, tambm, alguns modos de lanamento disponvel como sinalizadores para a inteno pode no ser definida no manifesto.

ANDROID, uma viso geral Anderson Duarte de Amorim

58

Usando o arquivo de manifesto


Quando declarar uma atividade em seu arquivo de manifesto, voc pode especificar como a atividade deve associar com uma tarefa usando o atributo launchMode do elemento <activity>. O atributo launchMode especifica uma instruo sobre como a atividade deve ser lanada em uma tarefa. H quatro modos diferentes de lanamento voc pode atribuir ao atributo launchMode: "standard" (o modo padro) Padro. O sistema cria uma nova instncia da atividade na tarefa de que foi iniciado e mapeia a inteno a ele. A atividade pode ser instanciada vrias vezes, cada instncia pode pertencer a diferentes tarefas e uma tarefa pode ter mltiplas instncias. "singleTop" Se uma instncia da atividade j existe no topo da tarefa atual, o sistema mapeia da estncia atravs de uma chamada para o seu mtodo onNewIntent(), ao invs de criar uma nova instncia da atividade. A atividade pode ser instanciada vrias vezes, cada instncia pode pertencer a diferentes tarefas e uma tarefa pode ter mltiplas instncias (mas s se a atividade na parte superior da pilha de retorno no uma instncia existente da atividade). Por exemplo, suponha que uma tarefa que est na pilha consiste de uma atividade de raiz A com as atividades B, C e D no topo (a pilha ABCD, D est no topo). A inteno chega para uma atividade do tipo D. Se D tem o modo de lanamento padro "standard", uma nova instncia da classe lanada e se torna a pilha ABCDD. No entanto, se D est no modo de lanamento "singleTop", a instncia existente do D entregue inteno por meio onNewIntent(), porque est no topo da pilha, a pilha continua ABCD. No entanto, se a inteno chega para uma atividade do tipo B, ento, uma nova instncia de B adicionada pilha, mesmo se o seu modo de lanamento "singleTop". Nota: Quando uma nova instncia de uma atividade criada, o usurio pode pressionar a tecla Back para retornar atividade anterior. Mas quando uma ANDROID, uma viso geral Anderson Duarte de Amorim

59

instncia existente de uma atividade lida com uma nova inteno, o usurio no poder pressionar a tecla Voltar para retornar ao estado da atividade antes da nova inteno chegaram a onNewIntent(). "singleTask" O sistema cria uma nova tarefa e instancia a atividade na raiz da nova tarefa. No entanto, se uma instncia da atividade j existe em uma tarefa separada, o sistema mapeia a inteno da instncia existente atravs de um convite sua onNewIntent(), ao invs de criar uma nova instncia. Apenas uma instncia da atividade pode existir ao mesmo tempo. Nota: Embora a atividade comee em uma nova tarefa, a tecla BACK ainda retorna o usurio para a atividade anterior. "singleInstance" . O mesmo que "singleTask", exceto que o sistema no inicia qualquer outra atividade para a tarefa, segurando a instncia. A atividade sempre e nico membro dessa tarefa; quaisquer atividades iniciadas por este abrem um em uma tarefa separada. Como outro exemplo, o navegador Android declara que a atividade do navegador web deve sempre aberta em sua prpria tarefa, especificando o modo de lanamento singleTask no elemento <activity>. Isto significa que, se o aplicativo emite a inteno de abrir o navegador do Android, a sua atividade no colocada na mesma tarefa que a sua aplicao. Em vez disso, ou uma nova tarefa para o navegador iniciada ou, se o navegador j tem uma tarefa em execuo em segundo plano, essa tarefa antecipada para lidar com a nova inteno. Independentemente de uma atividade ser iniciada em uma nova tarefa ou na mesma tarefa como a atividade que comeou, a tecla BACK sempre leva o usurio para a atividade anterior. Entretanto, se voc iniciar uma atividade de sua tarefa (Tarefa A), que especifica o modo de lanamento sendo singleTask, ento a atividade pode ter uma instancia em background que pertence a uma tarefa com a sua prpria pilha de volta (Tarefa B). Neste caso, quando a tarefa B antecipada para lidar com uma nova

ANDROID, uma viso geral Anderson Duarte de Amorim

60

inteno, a tecla BACK navega de volta atravs das atividades na tarefa B antes de retornar atividade do topo da tarefa A. Figura 4 visualiza este tipo de cenrio.

Figura 4. A representao de como uma atividade com o modo de lanar "singleTask" adicionada pilha de volta. Se a atividade j faz parte de uma tarefa em segundo plano com a sua prpria pilha de volta (Tarefa B), ento toda a volta da pilha tambm vem para a frente, em cima da tarefa atual (Tarefa A).

Nota: O comportamento que voc especificar para a sua atividade com a launchMode pode ser anulado por bandeiras includas com a inteno de iniciar a sua atividade, como discutido na prxima seo.

Usando as opes de intenes


Ao iniciar uma atividade, voc pode modificar o padro de associao de uma atividade, incluindo na inteno que voc entrega a startActivity(). As bandeiras que podem ser usadas para modificar o comportamento padro so: FLAG_ACTIVITY_NEW_TASK Iniciar a atividade em uma nova tarefa. Se a tarefa j est em execuo para a atividade que voc est comeando agora, essa tarefa levada para o primeiro plano com o seu ltimo estado restaurado e a atividade recebe a nova inteno em onNewIntent().

ANDROID, uma viso geral Anderson Duarte de Amorim

61

Isso produz o mesmo comportamento que a "singleTask", discutido na seo anterior. FLAG_ACTIVITY_SINGLE_TOP Se a atividade que est sendo iniciado a atividade atual (no topo da pilha de volta), ento a instncia existente recebe uma chamada para onNewIntent(), em vez de criar uma nova instncia da atividade. Isso produz o mesmo comportamento que a "singleTop", discutido na seo anterior. FLAG_ACTIVITY_CLEAR_TOP Se a atividade a ser iniciada j est em execuo na tarefa atual, ento ao invs de lanar uma nova instncia da atividade, todas as outras atividades em cima dela so destrudas e essa inteno entregue instncia retomada da atividade (agora no topo, atravs onNewIntent()). No h nenhum valor para o launchMode que produz esse comportamento. FLAG_ACTIVITY_CLEAR_TOP mais freqentemente utilizado em conjunto com FLAG_ACTIVITY_NEW_TASK. Quando usados em conjunto, essas bandeiras so uma maneira de localizar uma atividade existente em outra tarefa e coloc-la em uma posio onde ela pode responder inteno. Nota: Se o modo de lanamento da atividade designada "standard", ela tambm removida da pilha e uma nova instncia lanada em seu lugar para lidar com o intuito de entrada. Isso porque uma nova instncia sempre criada para uma nova inteno, quando a modalidade de lanamento "standard.

Manipulao de afinidades
A afinidade indica a qual tarefa uma atividade prefere pertencer. Por padro, todas as atividades da mesma aplicao tm afinidade entre si. Ento, por padro, todas as atividades no mesmo aplicativo preferem estar na mesma tarefa. No entanto, voc pode modificar o padro de afinidade para uma atividade. Atividades definidas em diferentes aplicaes podem compartilhar uma afinidade, ou atividades definidas no mesmo aplicativo podem ter diferentes afinidades de tarefas.

ANDROID, uma viso geral Anderson Duarte de Amorim

62

Voc pode modificar a afinidade de uma atividade especfica com o atributo taskAffinity do <activity> elemento. O atributo taskAffinity tem um valor de seqncia, que deve ser exclusivo do nome do pacote padro declarada no elemento <manifest>, porque o sistema usa esse nome para identificar a afinidade de tarefas padro para o aplicativo. A afinidade entra em jogo em duas circunstncias: Quando a inteno que inicia uma atividade contm

FLAG_ACTIVITY_NEW_TASK. o Uma nova atividade , por padro, lanada na tarefa da atividade que chamou startActivity(). empurrada para o topo da pilha do chamador. No entanto, se a inteno passada para startActivity() contm o

FLAG_ACTIVITY_NEW_TASK, o sistema procura por uma tarefa diferente para abrigar a nova atividade. Muitas vezes, uma nova tarefa. No entanto, ele no tem que ser. Se j existe uma tarefa, com a mesma afinidade que a nova atividade, a atividade lanada nessa tarefa. Se no, ele comea uma nova tarefa. o Se este sinalizador faz uma atividade para iniciar uma nova tarefa e que o usurio pressiona a tecla HOME para deix-lo, deve haver alguma maneira para o usurio navegar de volta para a tarefa. Algumas entidades (como o gerente de comunicao) sempre iniciam as atividades em uma tarefa externa, nunca como parte de si prpria, assim eles sempre colocam FLAG_ACTIVITY_NEW_TASK nas intenes para passar a startActivity(). Se voc tiver uma atividade que pode ser invocada por uma entidade externa que possa usar esta bandeira, tome cuidado para que o usurio tenha uma maneira independente para voltar para a tarefa que comeou como um cone do lanador (a atividade radicular da tarefa tem uma inteno de filtro CATEGORY_LAUNCHER). Quando uma atividade tem seu atributo allowTaskReparenting definido como "true". Neste caso, a atividade pode se mover da tarefa que comeou para a tarefa que tem afinidade, quando essa tarefa vem em primeiro plano.

ANDROID, uma viso geral Anderson Duarte de Amorim

63

Por exemplo, suponha que uma atividade que relata as condies meteorolgicas em cidades selecionadas definida como parte de um aplicativo de viagens. Ele tem a mesma afinidade como outras atividades na mesma aplicao (a afinidade aplicativo padro) e permite que re-parentalidade com esse atributo. Quando uma de suas atividades inicia a atividade de reportar o tempo, inicialmente pertencente mesma tarefa que a sua atividade. No entanto, quando a tarefa da aplicao de viagens volta ao primeiro plano, a atividade de reportar oo tempo designada para essa tarefa e exibida dentro dela. Dica: Se um arquivo .apk contiver mais de uma "aplicao" do usurio, voc provavelmente vai querer usar o atributo taskAffinity para atribuir diferentes afinidades para as atividades associadas a cada "pedido".

Limpando a pilha de volta


Se o usurio deixar uma tarefa por um longo tempo, o sistema cancela a tarefa de todas as atividades exceto a atividade de raiz. Quando o usurio retorna para a tarefa novamente, somente a atividade da raiz restaurada. O sistema se comporta desta maneira, porque, depois de um longo perodo de tempo, os usurios provavelmente abandonaram o que faziam antes e esto retornando para a tarefa para comear algo novo. H alguns atributos de atividade que voc pode usar para modificar esse comportamento: alwaysRetainTaskState Se este atributo definido como "true" na atividade de raiz de uma tarefa, o comportamento padro que acabamos de descrever no acontece. A tarefa retm todas as atividades na sua pilha, mesmo aps um longo perodo. clearTaskOnLaunch Se este atributo definido como "true" na atividade de raiz de uma tarefa, a pilha limpa at a atividade de raiz sempre que o usurio deixa a tarefa e retorna a ela. Em outras palavras, o oposto do alwaysRetainTaskState. O usurio sempre retorna para a tarefa em seu estado inicial, mesmo aps estar deixando a tarefa por apenas um momento. ANDROID, uma viso geral Anderson Duarte de Amorim

64

finishOnTaskLaunch Esse atributo como clearTaskOnLaunch, mas opera em uma nica atividade, no em uma tarefa inteira. Ela tambm pode fazer alguma atividade ir embora, incluindo a atividade de raiz. Quando definido como "true", a atividade continua a ser parte da tarefa apenas para a sesso atual. Se o usurio sai e depois volta para a tarefa, ela no est mais presente.

Iniciando uma tarefa


Voc pode configurar uma atividade como o ponto de entrada para uma tarefa, dandolhe um filtro com a inteno "android.intent.action.MAIN" como a ao especificada e "android.intent.category.LAUNCHER" como a categoria especificada. Por exemplo:
<activity ... > <intent-filter ... > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> ... </activity>

A inteno do filtro deste tipo faz um cone e uma legenda para a atividade a ser exibida na tela do menu, dando aos usurios uma maneira de iniciar a atividade e para retornar para a tarefa que ele cria em qualquer momento depois de ter sido lanado. Esta segunda habilidade importante: o usurio deve ser capaz de deixar uma tarefa e, em seguida, voltar a ela mais tarde com o lanador de atividade. Por esta razo, os dois modos de iniciar as atividades que marcam o incio, como sempre, uma tarefa, "singleTask" e " "singleInstance" , devem ser usados somente quando a atividade tem um filtro ACTION_MAIN e CATEGORY_LAUNCHER. Imagine, por exemplo, o que poderia acontecer se o filtro estiver faltando: Uma inteno lana uma atividade "singleTask", iniciando uma nova tarefa, e o usurio passa algum tempo a trabalhar nessa tarefa. O usurio pressiona o HOME. A tarefa agora enviada para o fundo e fica invisvel. Porque ele no representado na tela do aplicativo, o usurio no tem como voltar para a tarefa. Para os casos onde voc no deseja que o usurio seja capaz de retornar a uma atividade, defina o elemento de <activity>, finishOnTaskLaunch, para "true".

ANDROID, uma viso geral Anderson Duarte de Amorim

65

Servios
Um Service um componente da aplicao que pode executar operaes de longa durao em segundo plano e no oferece uma interface de usurio. Outro componente do aplicativo pode iniciar um servio e vai continuar a rodar em segundo plano, mesmo se o usurio muda para outro aplicativo. Alm disso, um componente pode se ligar a um servio para interagir com ele e at mesmo realizar a comunicao entre processos (IPC). Por exemplo, um servio pode lidar com as transaes de rede, tocar msica, executar I/O, ou interagir com um provedor de contedo, todos no fundo. Um servio pode essencialmente de duas formas: Iniciado Um servio "iniciado" quando um componente da aplicao (como uma atividade) inicia-o chamando startService(). Uma vez iniciado, o servio pode ser executado em segundo plano por tempo indeterminado, mesmo se o componente que o comeou destrudo. Normalmente, um servio iniciado executa uma nica operao e no retorna um resultado para o chamador. Por exemplo, pode fazer o download ou upload de um arquivo pela rede. Quando a operao feita, o servio deve parar. Ligado Um servio "ligado" quando um componente da aplicao liga-se a ele chamando bindService(). Um servio vinculado oferece uma interface clienteservidor que permite que os componentes interajam com o servio, enviar pedidos, obter resultados, e at mesmo faz-lo atravs de processos de comunicao entre processos (IPC). Um servio vinculado s executado enquanto outro componente de aplicao est vinculado a ele. Vrios componentes podem ligar para o servio de uma s vez, mas quando todos eles se desvinculam, o servio destrudo. Embora essa documentao geralmente aborda esses dois tipos de servios separadamente, o servio pode funcionar nos dois sentidos, ele pode ser iniciado (para rodar indefinidamente) e tambm permitir a ligao. simplesmente uma questo de

ANDROID, uma viso geral Anderson Duarte de Amorim

66

saber se voc implementa a dupla de mtodos: onStartCommand() para permitir ao os componentes inici-lo e onBind() para permitir a ligao. Independentemente de sua aplicao ser iniciada, ligada, ou ambos, qualquer componente de aplicativo pode usar o servio (mesmo a partir de um aplicativo separado), da mesma forma que qualquer componente pode usar uma atividade iniciando-a com uma Intent. No entanto, voc pode declarar o servio como privado, no arquivo de manifesto, e bloquear o acesso de outros aplicativos. Ateno: O servio executado no segmento principal de sua hospedagem, o servio de processo no cria seu prprio segmento e no executado em um processo separado (a menos que voc especifique o contrrio). Isso significa que, se o servio vai fazer todo o trabalho intensivo da CPU ou o bloqueio de operaes (como a reproduo de MP3 ou de rede), voc deve criar um novo segmento dentro do servio para fazer esse trabalho. Ao utilizar uma thread separada, voc vai reduzir o risco de erros como aplicao no responde (ANR) e o thread principal do aplicativo pode permanecer dedicado interao do usurio com suas atividades.

O bsico
Voc deve utilizar um servio ou um thread?
O servio simplesmente um componente que pode ser executado em segundo plano, mesmo quando o usurio no est interagindo com o aplicativo. Assim, voc deve criar um servio s para o que voc precisa. Se voc precisa realizar o trabalho fora de sua linha principal, mas apenas enquanto o usurio est interagindo com o aplicativo, ento voc deve, provavelmente, criar uma nova thread e no um servio. Por exemplo, se voc quiser tocar algumas msicas, mas apenas quando sua atividade est em execuo, voc pode criar uma lista de discusso em onCreate(), comear a utilizar em onStart() , e depois parar em onStop(). Tambm considere usar AsyncTask ou HandlerThread, em vez da tradicional classe Thread. Lembre-se que se voc usar um servio, ele ainda executado no

ANDROID, uma viso geral Anderson Duarte de Amorim

67

Para criar um servio, voc deve criar uma subclasse de Service (ou

thread principal do aplicativo por padro, ento voc deve ainda criar um novo segmento dentro do servio se executa operaes intensivas ou bloqueio.

uma de suas subclasses existentes). Em sua execuo, necessrio substituir alguns mtodos de callback para lidar com aspectos essenciais do ciclo de vida do servio e fornecer um mecanismo de componentes para ligar para o servio, se for o caso. Os mtodos mais importantes de retorno so: onStartCommand() O sistema chama este mtodo quando outro componente, como uma atividade, solicita que o servio seja iniciado, chamando startService(). Uma vez que este mtodo executado, o servio iniciado e pode rodar em segundo plano por tempo indeterminado. Se voc implementar essa, sua a responsabilidade parar o servio quando seu trabalho feito, chamando stopSelf() ou stopService(). (Se voc apenas quiser fornecer ligao, voc no precisa aplicar esse mtodo.) onBind() O sistema chama este mtodo quando um outro componente quer se vincular com o servio (por exemplo, executar RPC), chamando bindService(). Na implementao deste mtodo, voc deve fornecer uma interface que os clientes usam para se comunicar com o servio, retornando um IBinder. Voc sempre deve implementar este mtodo, mas se voc no quer permitir a ligao, ento voc deve retornar null. onCreate() O sistema chama este mtodo quando o servio criado, para executar os procedimentos de configurao (antes de chamar qualquer onStartCommand() ou onBind()). Se o servio j est em execuo, este mtodo no chamado. onDestroy() O sistema chama este mtodo quando o servio no mais usado e est sendo destrudo. Seu servio deve implementar isso para limpar quaisquer recursos, tais como threads, ouvintes registrados, receptores, etc. Esta a ltima chamada que o servio recebe. ANDROID, uma viso geral Anderson Duarte de Amorim

68

Se um componente inicia o servio chamando startService() (o que resulta em uma chamada para onStartCommand()), o servio continua funcionando at que ele pare com stopSelf() ou outro componente deixa-o chamando stopService(). Se um componente chama bindService() para criar o servio (e onStartCommand() no chamado), o servio funciona somente enquanto o componente est ligado a ele. Depois que o servio desvinculado de todos os clientes, o sistema se destri. O sistema Android fora a parada de um servio somente quando estiver com pouca memria e deve recuperar os recursos do sistema para a atividade que tem o foco do usurio. Se o servio est vinculado a uma atividade que tem o foco do usurio, ento menos provvel de ser morto, e se o servio declarado a ser executado no primeiro plano (discutido mais tarde), ento ele quase nunca vai ser morto. Caso contrrio, se o servio foi iniciado e est rodando h muito tempo, ento o sistema ir baixar a sua posio na lista de tarefas em segundo plano ao longo do tempo e o servio se tornar altamente suscetvel a matar-se - se o servio iniciado, ento voc deve projet-lo elegantemente para lanar reincio pelo sistema. Se o sistema mata o seu servio, ele reinicia logo que os recursos se tornam novamente disponveis (embora isso tambm dependa do valor que voc retornar do onStartCommand(), como ser discutido mais tarde).

Declarando um servio no manifesto


Como atividades (e outros componentes), voc deve declarar todos os servios do arquivo de manifesto do aplicativo. Para declarar seu servio, adicione um elemento <service> como um filho do elemento <application>. Por exemplo:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>

Existem outros atributos que voc pode incluir no <service> para definir propriedades, como as permisses necessrias para iniciar o servio e o processo em que o servio deve ser executado.

ANDROID, uma viso geral Anderson Duarte de Amorim

69

Assim como uma atividade, um servio pode definir filtros que permitem a inteno de outros componentes para invocar o servio utilizando as intenes implcitas. Ao declarar a inteno de filtros, componentes de qualquer aplicativo instalados no aparelho do usurio podem, potencialmente, iniciar o seu servio se o servio de declarar a inteno de filtro que corresponde inteno outro aplicativo passa a startService() . Se voc planeja usar o seu servio apenas localmente (as outras aplicaes no o usam), ento voc no precisa (e no deve) prestar quaisquer filtros de inteno. Sem qualquer inteno de filtros, voc deve iniciar o servio usando uma inteno explcita dos nomes de classe do servio. Alm disso, voc pode garantir que seu servio seja privado, basta somente voc incluir o atributo android:exported e defini-lo como "false". eficaz mesmo se o servio fornece filtros de inteno.

Criando um servio iniciado


Um servio iniciado que se um de outro Segmentao Android 1.6 ou inferior Se voc estiver construindo uma aplicao para o Android 1.6 ou inferior, voc precisa implementar onStart(), em vez de componente inicia chamando

startService(), resultando em uma chamada para o mtodo onStartCommand() do servio. Quando um servio iniciado, ele tem um ciclo de vida que independente do componente que comeou e o servio pode funcionar em segundo plano por tempo indeterminado, mesmo se o componente que o comeou destrudo. Como tal, o servio deve parar quando seu trabalho feito chamando stopSelf(), ou outro componente pode par-lo, chamando stopService().

onStartCommand() (no Android 2.0, onStart() foi depreciado em favor do onStartCommand()). Para obter mais informaes sobre a prestao de compatibilidade com

verses do Android superiores a 2.0, consulte a documentao de

onStartCommand().

Um componente de aplicao, como uma atividade, pode iniciar o servio chamando startService() e passando uma Intent que especifica o servio e inclui todos os dados para o servio deve usar. O servio recebe essa Intent no mtodo onStartCommand().

ANDROID, uma viso geral Anderson Duarte de Amorim

70

Por exemplo, suponha que uma atividade precisa salvar alguns dados para um banco de dados on-line. A atividade pode iniciar um servio e entreg-lo para guardar os dados, passando a inteno de startService(). O servio recebe a inteno em

onStartCommand(), se conecta Internet e executa a operao de banco de dados. Quando a transao estiver concluda, o servio o pra e ele destrudo. Ateno: Um servio executa no mesmo processo do aplicativo no qual ele declarado e na thread principal da aplicao, por padro. Assim, se o servio realiza intensivo ou o bloqueio de operaes, enquanto o usurio interage com uma atividade a partir do mesmo aplicativo, o servio vai abrandar o desempenho da atividade. Para evitar afetar o desempenho do aplicativo, voc deve iniciar uma nova thread dentro do servio. Tradicionalmente, h duas classes que voc pode estender para criar um servio iniciado: Service Esta a classe base para todos os servios. Quando voc estender essa classe, importante que voc crie um novo segmento para fazer todo o trabalho, pois o servio usa a linha principal do aplicativo, por padro, o que poderia diminuir o desempenho de qualquer atividade de sua aplicao que est rodando. IntentService Esta uma subclasse de Service que utiliza um thread de trabalho para lidar com todos os pedidos de incio, um de cada vez. Esta a melhor opo se voc no exigir que o servio de lidar com vrias solicitaes em simultneo. Tudo que voc precisa fazer implementar onHandleIntent(), que recebe a inteno de cada solicitao de incio para que voc possa fazer o trabalho de fundo.

Estendendo a classe IntentService


Porque a maioria dos servios iniciados no precisam lidar com mltiplas solicitaes ao mesmo tempo (que pode realmente ser um cenrio perigoso de multi-threading), melhor se voc implementar o seu servio usando o IntentService. O IntentService faz o seguinte:

ANDROID, uma viso geral Anderson Duarte de Amorim

71

Cria um thread de trabalho padro que executa todas as intenes entregues ao onStartCommand() em separado do thread principal de sua aplicao. Cria uma fila de trabalho que passa uma inteno de cada vez para seu onHandleIntent() de execuo, para que no tenha que se preocupar com multithreading. Interrompe o servio, aps todos os pedidos de incio ter sido manipulados, ento voc nunca tem que chamar stopSelf(). Fornece implementao padro de onBind() que retorna nulo. Fornece uma implementao padro de onStartCommand() que envia a inteno da fila de trabalho e, em seguida, onHandleIntent() de execuo. Tudo isto se acrescenta ao fato de que tudo que voc precisa fazer implementar onHandleIntent() para fazer o trabalho fornecido pelo cliente. (Embora, voc tambm precisa fornecer um construtor pequeno para o servio). Aqui est um exemplo de implementao de IntentService :
public class HelloIntentService extends IntentService { /** * A constructor is required, and must call the super IntentService(String) * constructor with a name for the worker thread. */ public HelloIntentService() { super("HelloIntentService"); } /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as appropriate. */ @Override protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { }

ANDROID, uma viso geral Anderson Duarte de Amorim

72

} } } }

Isso tudo que voc precisa: um construtor e uma implementao de onHandleIntent(). Se voc decidir tambm substituir os mtodos de retorno de chamada, tais como onCreate(), onStartCommand(), ou onDestroy(), no se esquea de chamar a implementao de super, de modo que o IntentService possa lidar corretamente com a vida do thread. Por exemplo, onStartCommand() deve retornar a implementao padro (que como a inteno entregue a onHandleIntent()):
@Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); return super.onStartCommand(intent,flags,startId); }

Alm do onHandleIntent(), o nico mtodo a partir do qual voc no precisa chamar o super classe onBind() (mas voc s precisa implementar caso o servio permita a ligao).

Estendendo a classe de servio


Como voc viu na seo anterior, utilizar IntentService faz sua implementao de um servio iniciado muito simples. Se, no entanto, necessrio o seu servio executar multi-threading (em vez de processar pedidos atravs da fila de trabalho), ento voc pode estender a classe Service para lidar com cada inteno. Para efeito de comparao, o cdigo de exemplo a seguir uma implementao do Service que executa o mesmo trabalho exatamente como o exemplo acima usando IntentService. Ou seja, para cada solicitao, ele usa um thread para executar o trabalho e os processos de um nico pedido por vez.
public class HelloService extends Service { private Looper mServiceLooper; private ServiceHandler mServiceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) {

ANDROID, uma viso geral Anderson Duarte de Amorim

73

super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; mServiceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; }

ANDROID, uma viso geral Anderson Duarte de Amorim

74

@Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }

ANDROID, uma viso geral Anderson Duarte de Amorim

75

Como voc pode ver, d muito mais trabalho do que usar um IntentService. No entanto, como voc lida com cada chamada para onStartCommand() por si s, voc pode executar vrias solicitaes em simultneo. Isso no o que este exemplo faz, mas se isso que voc quer ento voc pode criar um novo tpico para cada pedido e execut-los imediatamente (em vez de aguardar a solicitao anterior para terminar). Observe que o mtodo onStartCommand() deve retornar um inteiro. O inteiro um valor que descreve como o sistema deve continuar o servio a partir do evento em que o sistema o mata (como discutido acima, a implementao padro para IntentService trata isso para voc, mas voc capaz de modific-lo). O valor de retorno de onStartCommand() deve ser uma das seguintes constantes: START_NOT_STICKY Se o sistema mata o servio aps onStartCommand() retornar, no recria o servio, salvo se houver pendncia de intenes para entregar. Esta a opo mais segura para evitar a execuo de seu servio quando no for necessrio e quando a sua aplicao pode simplesmente reiniciar os trabalhos inacabados. START_STICKY Se o sistema mata o servio aps onStartCommand() retornar, recria o servio e chamar onStartCommand(), mas no entrega novamente a ltima inteno. Em vez disso, o sistema chama onStartCommand() com uma inteno nula, a menos que houver pendncia de intenes para iniciar o servio, nesse caso, os propsitos so entregues. Isso adequado para media players (ou afins) que no esto executando comandos, mas rodam indefinidamente espera de uma interao. START_REDELIVER_INTENT Se o sistema mata o servio aps onStartCommand() retornar, recria o servio e chama onStartCommand() com a ltima inteno que foi entregue para o servio. Quaisquer intenes pendentes so entregues em troca. Isso adequado para os servios que esto ativamente realizando um trabalho que deve ser imediatamente reiniciado, como baixar um arquivo.

ANDROID, uma viso geral Anderson Duarte de Amorim

76

Iniciando um servio
Voc pode iniciar um servio de uma atividade ou componente de outro aplicativo por meio de um Intent (especificando o servio para iniciar) para startService(). O sistema Android chama o mtodo onStartCommand() do servio do e passa a Intent. (Voc nunca deve chamar onStartCommand() diretamente.) Por exemplo, uma atividade pode iniciar o servio de exemplo na seo anterior (HelloSevice) com a inteno explcita com startService():
Intent intent = new Intent(this, HelloService.class); startService(intent);

O startService() retorna imediatamente e o sistema Android chama o mtodo onStartCommand() do servio. Se o servio no estiver sendo executado, o sistema chama primeiro onCreate(), em seguida, chama onStartCommand(). Se o servio no prov ligao, a inteno entregue com startService() o nico modo de comunicao entre o componente de aplicao e o servio. No entanto, se voc quiser o servio para enviar um resultado de volta, o cliente que inicia o servio pode criar uma PendingIntent para uma transmisso (com getBroadcast()) e entreg-lo ao servio da Intent que inicia o servio. O servio pode ento usar a transmisso para fornecer um resultado. Vrios pedidos para iniciar o resultado do servio em vrias correspondncias chamam o onStartCommand() do servio. No entanto, apenas um pedido para parar o servio (com stopSelf() ou stopService()) necessrio.

Parando um servio
O servio iniciado deve gerenciar seu prprio ciclo de vida. Ou seja, o sistema no para ou destri o servio a menos que ele deva recuperar a memria do sistema e o servio continua a funcionar aps onStartCommand() retornar. Assim, o servio deve parar, chamando stopSelf() ou outro componente pode par-lo, chamando stopService(). Uma vez solicitado a parar com stopSelf() ou stopService(), o sistema destri o servio o mais rapidamente possvel. No entanto, se o servio trabalha com pedidos mltiplos para onStartCommand() ao mesmo tempo, ento voc no deve interromper o servio quando tiver terminado o ANDROID, uma viso geral Anderson Duarte de Amorim

77

processamento de um pedido inicial, porque voc pode ter uma vez recebido um pedido novo comeo (parando no final do primeiro pedido iria encerrar a segunda). Para evitar esse problema, voc pode usar stopSelf(int) para garantir que o seu pedido para parar o servio sempre baseado no incio pedido mais recente. Ou seja, quando voc chamar stopSelf(int), voc passa o ID do pedido inicial (o startId entregue para onStartCommand()) ao qual o pedido de parada corresponde. Ento, se o servio recebeu um pedido antes de voc fosse capaz de chamar stopSelf(int) , o ID no corresponder e o servio no vai parar. Ateno: importante que o aplicativo pare seus servios quando o trabalho est pronto, para evitar o desperdcio de recursos do sistema e consumo de bateria. Se necessrio, outros componentes podem interromper o servio pela chamada de stopService(). Mesmo se voc permitir chamada ao servio, voc deve sempre parar o servio a si mesmo se ele j recebeu uma chamada para onStartCommand().

Criando um servio vinculado


Um servio vinculado aquele que permite que os componentes do aplicativo se vinculem a ele chamando bindService() para criar uma ligao de longa data (e geralmente no permitem aos componentes inici-lo, chamando startService()). Voc deve criar um servio ligado quando voc quiser interagir com o servio de atividades e outros componentes em seu aplicativo ou para expor algumas das funcionalidades do aplicativo para outros aplicativos, atravs da comunicao entre processos (IPC). Para criar um servio vinculado, voc deve implementar o mtodo onBind()para retornar um IBinder que define a interface de comunicao com o servio. Outros componentes do aplicativo pode ento chamar bindService() para recuperar a interface e comear a chamar os mtodos do servio. O servio s vive para servir o componente de aplicao que ligado a ele, ento quando no h componentes vinculados ao servio, o sistema o destri (voc no precisa parar um servio ligado no jeito que voc tem quando o servio iniciado atravs onStartCommand()). Para criar um servio vinculado, a primeira coisa que voc deve fazer definir a interface que especifica como um cliente pode se comunicar com o servio. Essa interface entre o servio e o cliente deve ser uma implementao de IBinder e o que o ANDROID, uma viso geral Anderson Duarte de Amorim

78

seu servio deve retornar a partir do mtodo de retorno onBind(). Uma vez que o cliente recebe a IBinder , pode comear a interagir com o servio por meio dessa interface. Vrios clientes podem se ligar ao servio de uma s vez. Quando um cliente concluiu a interao com o servio, ele chama unbindService() para se desvincular. Uma vez que no h clientes vinculados ao servio, o sistema destri o servio.

Enviando notificaes para o usurio


Uma vez em execuo, um servio pode notificar o usurio de eventos usando notificaes toast ou notificaes da barra de status. Uma notificao toast uma mensagem que aparece na superfcie da janela atual por um momento e depois desaparece, enquanto uma notificao de barra de status fornece um cone na barra de status com uma mensagem, que o usurio pode selecionar a fim de tomar uma ao (como iniciar uma atividade). Normalmente, uma notificao de barra de status a melhor tcnica quando algum trabalho de fundo tenha sido concludo (como um download do arquivo completo) e agora o usurio pode agir sobre ela. Quando o usurio seleciona a notificao a partir da viso expandida, a notificao pode iniciar uma atividade (tal como para visualizar o arquivo baixado).

Executando um servio em primeiro plano


Um servio de primeiro plano um servio que considerado como sendo algo que o usurio esteja atento e, portanto, no um candidato para o sistema matar quando com pouca memria. Um servio de primeiro plano deve prever uma notificao na barra de status, que colocado abaixo da posio "em curso", o que significa que a notificao no pode ser dispensada a menos que o servio ou est parado ou foi removido do primeiro plano. Por exemplo, um leitor de msica que toca a partir de um servio, deve ser definido para ser executado em primeiro plano, porque o usurio est explicitamente consciente do seu funcionamento. A notificao na barra de status pode indicar a msica atual e permitir que o usurio inicie uma atividade para interagir com o leitor de msica.

ANDROID, uma viso geral Anderson Duarte de Amorim

79

Para solicitar que o servio seja executado em primeiro plano, chame startForeground(). Este mtodo tem dois parmetros: um nmero inteiro que identifica a notificao e a notificao na barra de status. Por exemplo:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis()); Intent notificationIntent = new Intent(this, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent); startForeground(ONGOING_NOTIFICATION, notification);

Para remover o servio do primeiro plano, chama-se stopForeground(). Este mtodo tem um valor booleano, indicando se deseja remover a notificao de barra de status tambm. Este mtodo no para o servio. No entanto, se voc parar o servio enquanto ele ainda est executando em primeiro plano a notificao tambm removida. Nota: Os mtodos startForeground() e stopForeground() foram introduzidos no Android 2.0 (API Nvel 5).

Gerenciando ciclo de vida de um servio


O ciclo de vida de um servio muito mais simples do que o de uma atividade. No entanto, ainda mais importante que voc preste ateno forma como o servio criado e destrudo, porque um servio pode ser executado em segundo plano, sem que o utilizador perceba. O ciclo de vida do servio desde quando ele criado at quando ele destrudo - pode seguir dois caminhos diferentes: O servio comeou O servio criado quando um outro componente chama startService(). O servio executado indefinidamente e, em seguida, deve ser parado chamando stopSelf(). Outro componente tambm pode interromper o servio pela chamada de stopService(). Quando o servio for interrompido, o sistema o destri. Um servio vinculado O servio criado quando um outro componente (um cliente) chama bindService(). O cliente se comunica com o servio atravs de uma interface IBinder. O cliente

ANDROID, uma viso geral Anderson Duarte de Amorim

80

pode fechar a conexo chamando unbindService(). Vrios clientes podem chamar o mesmo servio e quando todos eles desvincularem-se, o sistema destri o servio. (O servio no precisa parar si mesmo). Estes dois caminhos no so totalmente distintos. Ou seja, voc pode chamar um servio que j foi iniciado com startService(). Por exemplo, um servio de msica de fundo pode ser iniciado chamando startService() com uma Intent que identifica a msica a tocar. Mais tarde, possivelmente quando o usurio deseja exercer algum controle sobre o player ou obter informaes sobre a msica atual, uma atividade pode se ligar ao servio chamando bindService(). Em casos como este, stopService() ou stopSelf() no chegam a parar o servio at que todos os clientes se desacoplem.

Aplicando o ciclo de vida dos callbacks


Como uma atividade, um ciclo de vida do servio tem mtodos de retorno que voc pode implementar para monitorar as mudanas no estado do servio e realizar o trabalho no momento oportuno. O seguinte esqueleto de servio demonstra todos os mtodos de ciclo de vida:

Figura 2. O ciclo de vida do servio. O diagrama esquerda mostra o ciclo de vida quando o servio criado com startService() e o diagrama da direita mostra o ciclo de vida quando o servio criado com bindService().

ANDROID, uma viso geral Anderson Duarte de Amorim

81

public class ExampleService extends Service { int mStartMode; // indicates how to behave if the service is killed IBinder mBinder; // interface for clients that bind boolean mAllowRebind; // indicates whether onRebind should be used @Override public void onCreate() { // The service is being created } @Override public int onStartCommand(Intent intent, int flags, int startId) { // The service is starting, due to a call to startService() return mStartMode; } @Override public IBinder onBind(Intent intent) { // A client is binding to the service with bindService() return mBinder; } @Override public boolean onUnbind(Intent intent) { // All clients have unbound with unbindService() return mAllowRebind; } @Override public void onRebind(Intent intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } @Override public void onDestroy() { // The service is no longer used and is being destroyed } }

Nota: Ao contrrio mtodos de retorno do ciclo de vida da atividade, voc no obrigado a chamar a implementao da superclasse dos mtodos de callback. Ao implementar esses mtodos, voc pode controlar dois loops aninhados do ciclo de vida do servio: A vida inteira de um servio acontece entre o momento onCreate() ser chamado e o tempo onDestroy() retornado. Como uma atividade, um servio tem a sua configurao inicial em onCreate() e libera todos os recursos remanescentes em onDestroy(). Por exemplo, um servio de reproduo de msica pode criar o segmento onde a msica ser tocada em onCreate(), ento para a thread em onDestroy().

ANDROID, uma viso geral Anderson Duarte de Amorim

82

Os mtodos onCreate() e onDestroy() so chamados para todos os servios, sejam eles criados por startService() ou bindService() . A vida ativa de um servio comea com uma chamada de um onStartCommand() ou onBind(). Cada mtodo entrega a Intent que foi passado tanto startService() quanto bindService(), respectivamente. Se o servio for iniciado, o tempo de vida ativa termina ao mesmo tempo em que toda a vida termina (o servio continua ativo mesmo aps onStartCommand() retornar). Se o servio est vinculado, a vida ativa termina quando onUnbind() retorna. Nota: Apesar de um servio iniciado ser interrompido por uma chamada para uma stopSelf() ou stopService(), no h um retorno para o respectivo servio (no h onStop() de callback). Ento, a menos que o servio esteja vinculado a um cliente, o sistema destri quando o servio for interrompido, onDestroy() o retorno recebido apenas. A figura 2 ilustra os mtodos tpicos de retorno de um servio. Embora a figura separa os servios que so criados por startService() daquelas criadas pelos bindService() , tenha em mente que qualquer servio, no importa como ele iniciado, pode potencialmente permitir que os clientes chamem-no. Assim, um servio que foi inicialmente iniciado com onStartCommand() (por um cliente chamando startService() ) pode ainda receber uma chamada para onBind() (quando um cliente solicita bindService()).

ANDROID, uma viso geral Anderson Duarte de Amorim

83

Servios vinculados
Um servio vinculado o servidor em uma interface cliente-servidor. O servio permite que os componentes ligados (como em atividades) vinculem-se ao servio, enviem pedidos, recebam respostas, e at mesmo realizem a comunicao entre processos (IPC). Um servio ligado normalmente vive apenas enquanto ela serve a outro componente da aplicao e no executado em segundo plano por tempo indeterminado.

O bsico
Um servio ligado uma implementao Service que da permite classe que

Vinculao a um servio iniciado


Conforme discutido no captulo sobre Servio, voc pode criar um servio que seja iniciado e vinculado. Ou seja, o servio pode ser iniciado chamando startService(), que permite que o servio seja executado indefinidamente, e tambm permite que um cliente se amarre ao servio chamando bindService(). Se voc permitir que seu servio seja iniciado e ligado, em seguida, quando o servio for iniciado, o sistema no destruir o servio quando todos os clientes desacoplarem. Em vez disso, voc deve explicitamente parar o servio, chamando stopSelf() ou stopService(). Embora voc geralmente deva implementar onBind() ou onStartCommand(), s vezes necessrio aplicar a ambos. Por exemplo, um tocador de msica pode ser til para

outros aplicativos se liguem e interajam com ele. fornecer servio, implementar mtodo de ligao voc o para Para um deve onBind() Esse

retorno.

mtodo retorna um objeto IBinder que define a interface de programao podem que usar os para

clientes

interagir com o servio. Um cliente pode se ligar ao servio chamando

permitir o servio a ser executado indefinidamente e tambm fornecer vnculo. Desta forma, uma atividade pode iniciar o servio para jogar alguma msica e a msica continua a tocar mesmo se o usurio sai do aplicativo. Ento, quando o usurio retorna para a aplicao, a atividade pode ligar para o servio para recuperar o controle da reproduo. Certifique-se de ler a seo sobre Gerenciamento do ciclo de vida de um servio vinculado, para obter mais informaes sobre o ciclo de vida do servio, quando for feita adio de ligao para um servio iniciado.

bindService(). Quando isso acontecer, ele deve fornecer uma implementao de que

ServiceConnection,

monitora a conexo com o servio. bindService() O mtodo retorna

imediatamente sem um valor,

ANDROID, uma viso geral Anderson Duarte de Amorim

84

mas quando o sistema Android cria a conexo entre o cliente e o servio, ele chama onServiceConnected() na ServiceConnection para entregar o IBinder que o cliente pode usar para se comunicar com o servio. Vrios clientes podem se conectar ao servio de uma s vez. No entanto, o sistema chama o mtodo onBind() do servio para recuperar o IBinder somente quando o cliente liga-se em primeiro lugar. O sistema, em seguida, oferece os mesmos IBinder para quaisquer clientes que ligam, sem chamar onBind() novamente. Quando o libera ltimo cliente do servio, o sistema destri o servio (a menos que o servio tambm foi iniciado por startService() ). Quando voc implementar o seu servio vinculado, a parte mais importante definir a interface que o seu mtodo callback onBind() retorna. Existem algumas maneiras diferentes que voc pode definir o seu servio da interface IBinder e a seo a seguir discute cada tcnica.

Criando um servio ligado


Ao criar um servio que oferece ligao, voc deve fornecer um IBinder que fornece a interface de programao que os clientes podem utilizar para interagir com o servio. Existem trs maneiras com as quais voc pode definir a interface: Estendendo a classe Binder Se o servio privado para sua prpria aplicao e executado no mesmo processo do cliente (o que comum), voc deve criar a sua interface extendendo o Binder e retornando uma instncia a partir onBind(). O cliente recebe o Binder e pode us-lo para acessar diretamente os mtodos pblicos disponveis em qualquer um dos Binder implementados ou at mesmo o Service. Esta a tcnica preferida quando o servio apenas um trabalhador de fundo para o seu prprio aplicativo. A nica razo em que voc no deve criar a interface desta maneira porque o servio utilizado por outras aplicaes ou atravs de processos separados.

ANDROID, uma viso geral Anderson Duarte de Amorim

85

Usando um Messenger Se voc precisa de sua interface para trabalhar em processos diferentes, voc pode criar uma interface para o servio com um Messenger. Desta forma, o servio define um Handler, que responde a diferentes tipos de mensagem de objetos. Este Handler a base para um Messenger que podem compartilhar um IBinder com o cliente, permitindo que o cliente envie comandos para o servio usando mensagem de objetos. Alm disso, o cliente pode definir um Messenger prprio para que o servio possa enviar mensagens de volta. Esta a maneira mais simples para realizar a comunicao entre processos (IPC), porque o Messenger enfilera todas as solicitaes em um nico segmento para que voc no tenha que projetar seu servio a ser um thread-safe. Usando AIDL AIDL (Android Interface Definition Language) realiza todo o trabalho de decompor os objetos primitivos em que o sistema operacional possa entender atravs de processos para executar IPC. A tcnica anterior, usando um Messenger, realmente baseado em AIDL como a sua estrutura subjacente. Como mencionado acima, o Messenger cria uma fila de todas as solicitaes do cliente em um nico segmento, para que o servio receba solicitaes de um de cada vez. Se, no entanto, voc quiser que o seu servio lide com mltiplas solicitaes ao mesmo tempo, ento voc pode usar AIDL diretamente. Neste caso, o servio deve ser capaz de multi-threading e ser construdo thread-safe. Para usar AIDL diretamente, voc deve criar uma arquivo .aidl que define a interface de programao. As ferramentas do Android SDK usam esse arquivo para gerar uma classe abstrata que implementa a interface e lida com o IPC, que voc pode estender dentro do seu servio. Nota: A maioria dos aplicativos no devem usar AIDL para criar um servio ligado, porque ele pode exigir recursos de multithreading e pode resultar em uma implementao mais complicada. Como tal, AIDL no adequado para a maioria das aplicaes e este documento no explica como us-lo para seu servio.

ANDROID, uma viso geral Anderson Duarte de Amorim

86

Estendendo a classe Binder


Se o servio usado somente pela aplicao local e no precisa trabalhar em todos os processos, ento voc pode implementar seu prprio Binder que fornece o acesso direto do cliente com os mtodos pblicos no servio. Nota: Isto s funciona se o cliente e o servio esto no mesmo aplicativo e processo, o que mais comum. Por exemplo, isso iria funcionar bem para um aplicativo de msica que tem o efeito de vincular uma atividade a seu prprio servio de msica que est tocando no fundo. Veja como configur-lo: 1. Em seu servio, criar uma instncia do Binder que:
o o

contm mtodos pblicos que o cliente pode chamar retorna o atual Service, que tem mtodos pblicos que o cliente pode chamar

ou, retorna uma instncia de outra classe hospedada pelo servio com mtodos pblicos que o cliente pode chamar

2. 3.

Retornar essa instncia do Binder do mtodo de retorno onBind(). No cliente, receber a Binder do mtodo de retorno onServiceConnected() e fazer chamadas para o servio vinculado usando os mtodos fornecidos.

Nota: A razo pela qual o servio e o cliente devem estar no mesmo pedido porque o cliente pode converter o objeto retornado e chamar propriamente de sua API. O servio e o cliente tambm devem estar no mesmo processo, porque essa tcnica no exerce qualquer triagem em todos os processos. Por exemplo, aqui est um servio que oferece aos clientes o acesso a mtodos no servio por meio de um Binder de execuo:
public class LocalService extends Service { // Binder given to clients private final IBinder mBinder = new LocalBinder(); // Random number generator private final Random mGenerator = new Random();

ANDROID, uma viso geral Anderson Duarte de Amorim

87

/** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { // Return this instance of LocalService so clients can call public methods return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } /** method for clients */ public int getRandomNumber() { return mGenerator.nextInt(100); } }

O LocalBinder fornece o mtodo getService() de clientes para recuperar a instncia atual do LocalService. Isso permite aos clientes chamarem mtodos pblicos no servio. Por exemplo, os clientes podem chamar getRandomNumber() do servio. Aqui est uma atividade que se liga a LocalService e solicita getRandomNumber() quando um boto clicado:
public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) {

ANDROID, uma viso geral Anderson Duarte de Amorim

88

unbindService(mConnection); mBound = false; } } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute) */ public void onButtonClick(View v) { if (mBound) { // Call a method from the LocalService. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }

O exemplo acima mostra como o cliente liga para o servio usando uma implementao do ServiceConnection e o callback de onServiceConnected(). Nota: O exemplo acima no explicitamente desvinculado do servio, mas todos os clientes devem desvincular em um tempo adequado (por exemplo, quando a atividade pausa).

ANDROID, uma viso geral Anderson Duarte de Amorim

89

Usando um Messenger
Se voc precisar de seu servio para se comunicar com processos remotos, ento voc pode usar um Messenger para fornecer a interface para o servio. Esta tcnica permite realizar a
Comparado com AIVD Quando voc precisa realizar IPC, utilizar um Messenger para a sua interface mais simples do que implement-la com AIDL, porque Messenger enfilera todas as chamadas para o servio, que, uma interface AIDL pura envia pedidos

comunicao entre processos (IPC), sem a necessidade de utilizar AIDL. Aqui est um resumo de como usar um Messenger: O servio implementa um

simultneos para o servio, que deve, ento, lidar com multi-threading. Para a maioria das aplicaes, o servio no precisa executar multi-threading, portanto, usar um Messenger permite ao servio lidar com uma chamada ao mesmo tempo. Se importante que o seu servio seja multi-threaded, ento voc deve usar AIDL para definir sua interface.

Handler que recebe um callback para cada chamada de um cliente.

O Handler usado para criar uma Messenger (que uma referncia para o Handler). O Messenger cria um IBinder que o servio retorna para clientes de onBind(). Os clientes usam o IBinder para instanciar o Messenger (que faz referncia ao servio Handler), que o cliente usa para enviar mensagens para o servio. O servio recebe cada mensagem em seu Handler, especificamente, no mtodo handleMessage(). Desta forma, no existem "mtodos" para o cliente para chamar o servio. Em vez disso, o cliente fornece as "mensagens" (objetos Message) que o servio recebe em seu Handler. Aqui est um exemplo de servio simples que usa um Messenger interface:
public class MessengerService extends Service { /** Command to the service to display a message */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients.

ANDROID, uma viso geral Anderson Duarte de Amorim

90

*/ class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ final Messenger mMessenger = new Messenger(new IncomingHandler()); /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); } }

Observe que o mtodo handleMessage() no Handler onde o servio recebe a entrada Message e decide o que fazer, com base no membro what. Tudo o que um cliente precisa fazer criar um Messenger com base no IBinder retornado pelo servio e enviar uma mensagem usando o send(). Por exemplo, aqui uma atividade simples, que liga para o servio e oferece a mensagem MSG_SAY_HELLO para o servio:
public class ActivityMessenger extends Activity { /** Messenger for communicating with the service. */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean mBound; /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) {

ANDROID, uma viso geral Anderson Duarte de Amorim

91

// This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = new Messenger(service); mBound = true; } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; mBound = false; } }; public void sayHello(View v) { if (!mBound) return; // Create and send a message to the service, using a supported 'what' value Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to the service bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } }

ANDROID, uma viso geral Anderson Duarte de Amorim

92

Observe que este exemplo no mostra como o servio pode responder ao cliente. Se voc deseja que o servio responda, ento voc tambm precisa criar um Messenger no cliente. Ento, quando o cliente recebe a chamada onServiceConnected(), ele envia uma mensagem para o servio, que inclui o Messenger do cliente no parmetro replyTo d mtodo send(). Voc pode ver um exemplo de como fornecer mensagens bidirecionais no MessengerService.java (servio) e MessengerServiceActivities.java (cliente).

Vinculao a um servio
Componentes da aplicao (clientes) podem se ligar a um servio chamando bindService(). O sistema Android, em seguida, chama o servio de onBind(), mtodo que retorna um IBinder para interagir com o servio. A ligao assncrona, bindService() retorna imediatamente e no retorna a IBinder para o cliente. Para receber o IBinder, o cliente deve criar uma instncia de ServiceConnection e o passa para bindService(). O ServiceConnection inclui um mtodo de resposta que o sistema chama para entregar o IBinder. Nota: S as atividades, servios e provedores de contedo podem se ligar a um servio - voc no pode se ligar a um servio a partir de um receptor de broadcast. Assim, para ligar a um servio de seu cliente, voc deve: 1. Implementar ServiceConnection . A implementao deve substituir dois mtodos: onServiceConnected(): O sistema chama isso para entregar o IBinder retornado pelo mtodo onBind() do servio. onServiceDisconnected(): O sistema Android chama isso quando a conexo com o servio perdida inesperadamente, como quando o servio foi paralisada ou tenha sido morta. Isto no chamado quando o cliente libera. 2. Call bindService(), passando a implementao ServiceConnection.

ANDROID, uma viso geral Anderson Duarte de Amorim

93

3. Quando o sistema chama o mtodo de retorno onServiceConnected(), voc pode comear a fazer chamadas para o servio, utilizando os mtodos definidos pela interface. 4. Para desligar do servio, chame unbindService(). Quando o cliente for destrudo, ele ir desvincular-se do servio, mas voc deve sempre desvincular quando terminar a interao com o servio ou quando a atividade pausar, ento o servio pode parar enquanto no est sendo utilizado. Por exemplo, o seguinte trecho liga o cliente ao servio criado anteriormente por estender a classe Binder, ento tudo o que deve fazer o lanar o IBinder retornado ao LocalService e solicitar a LocalService:
LocalService mService; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } // Called when the connection with the service disconnects unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "onServiceDisconnected"); mBound = false; } };

Com este ServiceConnection, o cliente pode ligar para um servio, passando este para bindService(). Por exemplo:
Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

O primeiro parmetro de bindService() uma Intent que, explicitamente, nomeia o servio a ser vinculado (pensando que a inteno pode ser implcita). O segundo parmetro o objeto ServiceConnection. O terceiro parmetro um sinalizador que indica as opes para a ligao. Deve ser geralmente BIND_AUTO_CREATE, a fim de criar o servio se ainda no ANDROID, uma viso geral Anderson Duarte de Amorim

94

estiver vivo. Outros valores possveis so BIND_DEBUG_UNBIND e BIND_NOT_FOREGROUND, ou 0 para nenhum.

Notas adicionais
Aqui esto algumas anotaes importantes sobre a ligao a um servio: Voc deve sempre lanar excees DeadObjectException, que so lanados quando a conexo foi quebrada. Esta a nica exceo acionada por mtodos remotos. Os objetos so referncia contada atravs de processos. Voc normalmente dever emparelhar a ligao e desligamento durante a correspondente destruio e desmontagem de momentos do ciclo de vida do cliente. Por exemplo:
o

Se voc s precisa interagir com o servio, enquanto sua atividade visvel, voc deve se ligar durante onStart() e desvincular durante onStop().

Se voc quiser que a sua atividade receba as respostas, mesmo quando ele est parado no fundo, ento voc pode se ligar durante onCreate() e desvincular durante onDestroy(). Cuidado com o que isso implica que a sua atividade necessita para usar o servio durante todo o tempo ele est rodando (mesmo no fundo), por isso, se o servio est em outro processo, ento voc aumentar o peso do processo e torna-se mais provvel do sistema mat-lo.

Nota: Voc normalmente no deveria vincular e desvincular a sua atividade durante o onResume() e onPause(), porque esses retornos ocorrem em todas as transies do ciclo de vida e voc deve manter o processamento que ocorre nessas transies para um nvel mnimo. Alm disso, se h vrias atividades em sua aplicao para vincular o mesmo servio e no h uma transio entre duas dessas atividades, o servio pode ser destrudo e recriado como desassocia a atividade atual (durante a pausa) antes da prxima ligao (durante a retomada).

ANDROID, uma viso geral Anderson Duarte de Amorim

95

Gerenciando o ciclo de vida de um servio de associao

Figura 1. O ciclo de vida de um servio que iniciado e tambm permite a ligao.

Quando um servio desvinculado de todos os clientes, o sistema Android o destri (a menos foi iniciado com onStartCommand()). Como tal, voc no tem que gerenciar o ciclo de vida do seu servio se ele meramente um limite de servio - o sistema Android gerencia isso para voc saber se ele est ligado a algum cliente. No entanto, se voc optar por implementar o mtodo de retorno onStartCommand(), ento voc deve explicitamente parar o servio, porque o servio considerado agora a

ANDROID, uma viso geral Anderson Duarte de Amorim

96

ser iniciado. Neste caso, o servio executado at que o servio para com stopSelf() ou outro componente chama stopService(), independentemente se est ligado a outros clientes. Alm disso, se o servio iniciado e aceita a ligao, ento quando o sistema solicita sua onUnbind(), voc pode opcionalmente retornar true se voc gostaria de receber uma chamada para onRebind() na prxima vez que um cliente chama o servio (ao invs de receber uma chamada para onBind()). onRebind() retorna void, mas o cliente ainda recebe o IBinder na sua onServiceConnected(). A figura 1 ilustra a lgica para este tipo de ciclo de vida.

ANDROID, uma viso geral Anderson Duarte de Amorim

97

Processos e threads
Quando um componente de aplicativo se inicia e a aplicao no possui nenhum outro componente rodando, o sistema Android inicia um novo processo Linux para a aplicao com um nico thread. Por padro, todos os componentes do mesmo aplicativo executam no mesmo processo e thread (chamada de thread "main"). Se um componente do aplicativo iniciado e j existe um processo para aquela aplicao (porque um outro componente do aplicativo existe), ento o componente iniciado dentro desse processo e usa o mesmo thread de execuo. No entanto, voc pode arranjar para diferentes componentes em seu aplicativo para serem executados em processos separados, e voc pode criar threads adicionais para qualquer processo.

Processos
Por padro, todos os componentes do mesmo aplicativo executam no mesmo processo e a maioria das aplicaes no devem mudar isso. No entanto, se voc achar que voc precisa controlar a que processo um determinado componente pertence, pode faz-lo no arquivo de manifesto. A entrada de manifesto para cada tipo de elemento - <activity>, <service , <receiver> e <provider> - suporta um atributo android:process que pode indicar um processo em que esse componente deve ser executado. Voc pode definir esse atributo para que cada componente seja executado em seu prprio processo, ou que algumas componentes compartilham um processo, enquanto outros no. Voc tambm pode definir android:process de modo que os componentes de diferentes aplicaes sejam executados no mesmo processo - desde que as aplicaes compartilhem o mesmo ID de usurio do Linux e assinem com os mesmos certificados. O elemento <application> tambm suporta um atributos android:process, para definir um valor padro que se aplica a todos os componentes. Android pode decidir encerrar um processo em algum momento, quando houver pouca memria e exigido por outros processos que esto mais imediatamente servindo ao usurio. Componentes de aplicativos em execuo no processo que est morto so conseqentemente destrudos. Um processo iniciado novamente para esses componentes, quando h trabalho novamente para que eles faam.

ANDROID, uma viso geral Anderson Duarte de Amorim

98

Ao decidir quais os processos matar, o sistema Android pesa a sua importncia relativa para o usurio. Por exemplo, mais facilmente desligado um processo hospedando atividades que no so mais visveis na tela, em comparao com um processo hospedando atividades visveis. A deciso de encerrar um processo, portanto, depende do estado dos componentes em execuo no processo.

Ciclo de vida do processo


O sistema Android tenta manter um processo de candidatura pelo maior tempo possvel, mas, eventualmente, precisa remover os processos antigos para recuperar a memria para novos processos ou mais importantes. Para determinar quais os processos manter e quais matar, o sistema coloca cada processo em uma "hierarquia de importncia" com base nos componentes em execuo no processo e o estado desses componentes. Processos com menor importncia so eliminadas em primeiro lugar, em seguida, aqueles com a menor importncia seguinte, e assim por diante, sempre que necessrio para recuperar os recursos do sistema. H cinco nveis na hierarquia de importncia. A lista a seguir apresenta os diferentes tipos de processos em ordem de importncia (o primeiro processo o mais importante e morto por ltimo): 1. Processo em primeiro plano: Um processo que necessrio para que o usurio esteja fazendo atualmente. Um processo considerado em primeiro plano, se qualquer uma das seguintes condies forem verdadeiras: Abriga uma Activity com a qual o usurio est interagindo com (o mtodo onResume() da Activity foi chamado). Abriga um Service que est vinculado atividade que o usurio est interagindo. Abriga um Service que est sendo executado "em primeiro plano", o servio chamado startForeground(). Abriga um Service que est executando um ciclo de vida de seus retornos (onCreate(), onStart(), ou onDestroy()). Abriga um BroadcastReceiver que est executando a sua onReceive(). Geralmente, apenas um processo de background existe em um determinado momento. Eles so mortos apenas como um ltimo recurso - se a memria to

ANDROID, uma viso geral Anderson Duarte de Amorim

99

pouca que ele no pode continuar rodando. Geralmente, nesse ponto, o dispositivo atingiu um estado de paginao de memria, ento, matar alguns processos de primeiro plano necessrio para manter a interface de usurio sensvel. 2. Processo Visvel Um processo que no tem nenhum componente de primeiro plano, mas ainda pode afetar o que o usurio v na tela. Um processo considerado visvel se qualquer uma das seguintes condies forem verdadeiras: Abriga uma Activity que no est em primeiro plano, mas ainda visvel para o usurio (seu mtodo onPause() foi chamado). Isso pode ocorrer, por exemplo, se a atividade iniciou um plano de dilogo, que permite que a atividade anterior possa ser vista por trs dele. Abriga um Service que est vinculado a uma atividade (ou plano) visvel. Um processo visvel considerado extremamente importante e no vai ser morto a menos que isso necessrio para manter todos os processos de primeiro plano em execuo. 3. Processo de servio Um processo que est executando um servio que foi iniciado com o mtodo startService() e no se enquadra em nenhuma das duas categorias acima. Embora os processos de servio no estejam diretamente ligados a qualquer coisa que o usurio v, eles esto geralmente fazendo coisas que o usurio se preocupa (como a reproduo de msica no fundo ou baixando arquivo na rede), ento o sistema os mantm rodando, a menos que no haja memria suficiente para retlos, juntamente com o primeiro plano e processos visveis. 4. Processo em segundo plano Um processo que mantm uma atividade que no visvel para o usurio no momento (o mtodo onStop() da atividade foi chamado). Esses processos no tm impacto direto sobre a experincia do usurio, e o sistema pode mat-los a qualquer momento para recuperar a memria para primeiro plano, visibilidade, ou processo de servio. Normalmente, h muitos processos em execuo no

ANDROID, uma viso geral Anderson Duarte de Amorim

100

fundo, ento eles so mantidos em uma LRU (menos recentemente usada), lista para garantir que o processo com a atividade que mais recentemente foi visto pelo usurio o ltimo a ser morto. Se uma atividade implementa mtodos de seu ciclo de vida corretamente, e salva o seu estado atual, matar o seu processo no ter um efeito visvel sobre a experincia do usurio, pois quando o usurio navega de volta para a atividade, a atividade restaura todo o seu estado visvel. 5. Processo vazio Um processo que no possui todos os componentes do aplicativo ativos. A nica razo para manter esse tipo de processo vivo para fins de armazenamento em cache, para melhorar o tempo de inicializao da prxima vez que um componente precisa ser executado. O sistema mata muitas vezes estes processos a fim de equilibrar os recursos do sistema global entre os caches do processo e os cachs do kernel subjacente. Android enfileira um processo ao mais alto nvel que pode, com base na importncia do componente ativo no processo. Por exemplo, se um processo hospeda um servio e uma atividade visvel, o processo classificado como um processo visvel, e no um processo de servio. Alm disso, o ranking de um processo pode ser acrescido, pois outros processos so dependentes dele - um processo que est servindo a outro processo nunca pode ser menor classificado do que o processo que est servindo. Por exemplo, se um provedor de contedo em um processo A est a servir um cliente no processo de B, ou se um servio em um processo A est ligado a um componente no processo de B, processo A sempre considerado pelo menos to importante como o processo B. Porque um processo executando um servio melhor classificado do que um processo com atividades em segundo plano, uma atividade que inicia uma operao de longa durao pode muito bem comear um servio para essa operao, ao invs de simplesmente criar uma thread de trabalhador - particularmente se a operao provavelmente durar mais que a atividade. Por exemplo, uma atividade que carrega uma foto em um site deve iniciar um servio para realizar o upload, ento o upload pode continuar em segundo plano, mesmo se o usurio deixar a atividade. Usar um servio garante que a operao ter, pelo menos, prioridade "no processo do servio",

ANDROID, uma viso geral Anderson Duarte de Amorim

101

independentemente do que acontece com a atividade. Este o mesmo motivo que os receptores de broadcast devem contratar servios ao invs de simplesmente colocar operaes demoradas em um thread.

Thread
Quando uma aplicao lanada, o sistema cria um thread de execuo para o aplicativo, chamado de "main". Esta thread muito importante, pois responsvel por despachar os eventos para os apropriados widgets de interface de usurio, incluindo eventos de desenho. tambm o segmento em que sua aplicao interage com os componentes da UI Toolkit Android (componentes da android.widget e pacotes android.view). Como tal, o thread principal chamado tambm s vezes de UI thread. O sistema no cria um thread separado para cada instncia de um componente. Todos os componentes que so executados no mesmo processo so instanciados no thread de interface do usurio e as chamadas do sistema para cada componente so despachadas a partir desse thread. Conseqentemente, os mtodos que respondem s callbacks do sistema (como onKeyDown() para relatar as aes do usurio ou um mtodo de retorno do ciclo de vida) sempre executam no thread da interface do usurio do processo. Por exemplo, quando o usurio toca um boto na tela, seu thread UI do aplicativo despacha o evento de toque para o widget, que por sua vez, define seu estado pressionado e lana uma requisio invlida para a fila de eventos. O thread UI desenfilera a requisio e notifica o widget que deve se redesenhar. Quando o aplicativo executa um trabalho intensivo em resposta interao do usurio, este nico thread pode produzir mal desempenho a menos que voc implemente a sua aplicao de forma adequada. Especificamente, se tudo est acontecendo no thread de interface do usurio, realizando longas operaes, tais como acesso rede ou consultas de banco de dados, ir bloquear a interface toda. Quando o thread est bloqueado, nenhum evento pode ser enviado, incluindo eventos de desenho. Do ponto de vista do usurio, o aplicativo parece travar. Pior ainda, se o segmento de interface do usurio estiver bloqueado por mais de alguns segundos (cerca de 5 segundos atualmente) ao usurio apresentado o abominvel "aplicativo no responde" (ANR). O usurio pode, ento, decidir abandonar a aplicao e desinstal-la se est infeliz.

ANDROID, uma viso geral Anderson Duarte de Amorim

102

Alm disso, o Andoid UI Toolkit no thread-safe. Ento, voc no deve manipular a sua interface a partir de um thread de trabalho - voc deve fazer toda a manipulao de sua interface a partir de um thread UI. Assim, existem apenas duas regras para o modelo de thread nica no Android: 1. 2. No bloquear o thread de UI No acessar o Android UI Toolkit de fora do thread UI

Threads funcionais
Devido ao modelo de thread nico acima descrito, vital para a capacidade de resposta da interface do usurio do seu aplicativo que voc no bloqueie o thread. Se voc tiver de realizar operaes que no so instantneas, voc deve certificar-se de faz-las em threads separados ("background" ou threads "worker"). Por exemplo, abaixo est um cdigo para um usurio que faz o download de uma imagem de um thread separado e exibida em uma ImageView:
public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start(); }

Em princpio, isso parece funcionar bem, porque cria uma nova thread para lidar com a operao da rede. No entanto, ele viola a segunda regra do modelo de nica thread: no acessar o Android UI Toolkit de fora da UI-thread - esta amostra modifica o ImageView do thread de trabalho em vez do thread UI. Isso pode resultar em um comportamento indefinido e inesperado, que pode ser difcil e demorado para rastrear. Para corrigir esse problema, o Android oferece vrias maneiras para acessar a thread de interface do usurio a partir de outros threads. Aqui est uma lista de mtodos que podem ajudar: Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long)

ANDROID, uma viso geral Anderson Duarte de Amorim

103

Por

exemplo,

voc

pode

corrigir

cdigo

acima

usando

mtodo

View.post(Runnable):
public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); }

Agora, essa implementao thread-safe: o funcionamento da rede feito a partir de um segmento separado, enquanto o ImageView manipulado a partir do thread de interface de usurio. No entanto, como a complexidade da operao cresce, este tipo de cdigo pode ser complicado e difcil de manter. Para lidar com interaes mais complexas com um thread de trabalho, voc pode considerar usar um Handler, para processar as mensagens entregues a partir do thread. Talvez a melhor soluo, porm, estender a classe AsyncTask, o que simplifica a execuo de tarefas do thread de trabalho que precisam interagir com a interface do usurio.

Usando AsyncTask
AsyncTask permite executar trabalho assncrono em sua interface com o usurio. Ela executa as operaes de bloqueio em um segmento de trabalho e, em seguida, publica os resultados no segmento de interface do usurio, sem que voc precise lidar com tpicos e/ou manipuladores de si mesmo. Para us-lo, voc deve incorporar AsyncTask e implementar o mtodo de retorno doInBackground(), que executado em um pool de threads de background. Para atualizar sua interface, voc deve implementar onPostExecute(), que fornece o resultado da doInBackground() e executado no thread da interface do usurio, assim voc pode escolher atualizar o UI. Voc pode ento executar a tarefa, chamando execute() do thread UI.

ANDROID, uma viso geral Anderson Duarte de Amorim

104

Por exemplo, voc pode implementar o exemplo anterior usando AsyncTask desta forma:
public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png"); } private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } /** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); } }

Agora a interface do usurio segura e o cdigo simples, porque separa o trabalho na parte que deve ser feita em um thread de trabalho e a parte que deve ser feita no thread de interface de usurio. Voc deve ler o AsyncTask de referncia para um entendimento completo de como usar essa classe, mas aqui est uma viso geral de como funciona: Voc pode especificar o tipo dos parmetros, os valores de progresso e o valor final da tarefa, usando genricos O mtodo doInBackground() executado automaticamente em um segmento de trabalho onPreExecute(), onPostExecute(), e onProgressUpdate() so invocados no thread de interface do usurio O valor retornado por doInBackground() enviado para onPostExecute() Voc pode chamar publishProgress() em qualquer outro momento do doInBackground() para executar onProgressUpdate() na thread da UI Voc pode cancelar a tarefa a qualquer hora, de qualquer thread Ateno: Outro problema que se pode encontrar ao usar um segmento de trabalho reincios inesperados na sua atividade devido a uma alterao de configurao em tempo de execuo (como quando o usurio muda a orientao da tela), que podem

ANDROID, uma viso geral Anderson Duarte de Amorim

105

destruir seu segmento de trabalho. Para ver como voc pode manter a sua tarefa durante um desses reincios e como fazer corretamente um cancelamento da tarefa quando a atividade for destruda, veja o cdigo fonte para o aplicativo de amostra da Prateleira.

Mtodos de Thread-safe
Em algumas situaes, os mtodos a implementar poderiam ser chamados de mais de um thread e, portanto, deve ser escrito para ser thread-safe. Isto principalmente verdadeiro para mtodos que podem ser chamados remotamente, como mtodos de um servio vinculado. Quando uma chamada de um mtodo implementado em um IBinder se origina no mesmo processo em que o IBinder est executando, o mtodo executado na thread de quem chamou. No entanto, quando a chamada originada em outro processo, o mtodo executado em um thread escolhido de um pool de threads que o sistema mantm no mesmo processo que o IBinder (no executado no thread da interface do usurio do processo). Por exemplo, considerando que um mtodo onBind() do servio seria chamado do de interface do usurio do processo de servio, mtodos implementados no objeto que onBind() retorna (por exemplo, uma subclasse que implementa mtodos RPC) seriam chamados threads no pool. Como um servio pode ter mais de um cliente, mais de uma pool de threads pode envolver o mesmo mtodo IBinder, ao mesmo tempo. Mtodos IBinder devem, portanto, ser implementadas para ser thread-safe. Da mesma forma, um provedor de contedo pode receber dados de pedidos que se originam em outros processos. Embora o ContentResolver e ContentProvider ocultam os detalhes de como a comunicao entre processos gerenciada, mtodos ContentProvider que respondem a esses pedidos - os mtodos query(), insert(), delete(), update(), e getType() so chamados a partir de um pool de threads no processo de provedor de contedo, e no o thread UI para o processo. Como esses mtodos podem ser chamados a partir de qualquer nmero de threads ao mesmo tempo, eles tambm devem ser implementados para ser thread-safe.

Comunicao entre processos


Android oferece um mecanismo para comunicao entre processos (IPC) atravs de chamadas de procedimento remoto (RPCs), em que um mtodo chamado por uma ANDROID, uma viso geral Anderson Duarte de Amorim

106

atividade ou um componente de outro aplicativo, mas executado remotamente (em outro processo), com qualquer resultado retornado de volta para o chamador. Isto implica a decomposio de uma chamada de mtodo e de seus dados a um nvel que o sistema operacional possa entender, transmiti-lo a partir do processo do processo local e espao de endereamento para o processo remoto e espao de endereo, em seguida, remontar e reencenar a chamada. Os valores de retorno so transmitidos na direo oposta. Android fornece todo o cdigo para executar essas operaes IPC, para que voc possa se concentrar na definio e implementao da interface de programao do RPC. Para executar o IPC, o aplicativo deve ligar para um servio, utilizando bindService().

ANDROID, uma viso geral Anderson Duarte de Amorim

107

Interface de usurio
Em um aplicativo do Android, a interface do usurio construda usando objetos View e ViewGroup. Existem muitos tipos de views e view groups, cada um dos quais um descendente da classe View. Objetos view so as unidades bsicas de expresso da interface do usurio na plataforma Android. A classe View serve como base para as subclasses chamadas de "widgets", que oferecem completa implementao de objetos de interface do usurio, como campos de texto e botes. A classe ViewGroup serve como base para as subclasses chamadas de "layouts", que oferecem diferentes tipos de layout de arquitetura, como a linear, tabular e relativa. Um objeto View uma estrutura de dados, cujas propriedades armazenam os parmetros de layout e de contedo para uma determinada rea retangular da tela. Um objeto View lida com sua prpria medida, layout, desenho, mudana de foco, scrolling e interaes telcla/gesto para a rea retangular da tela na qual ele reside. Como um objeto na interface do usurio, uma View tambm um ponto de interao para o usurio e o receptor de eventos de interao.

Hierarquia de view
Sobre a plataforma Android, voc define uma interface de atividades, usando uma hierarquia de view e ns ViewGroup, como mostrado no diagrama abaixo. Esta rvore de hierarquia pode ser to simples ou complexa como voc precisa que ela seja, e voc pode constru-la usando o conjunto do Android de widgets e layouts pr-definidos, ou com views customizados que voc mesmo cria.

ANDROID, uma viso geral Anderson Duarte de Amorim

108

A fim de fixar a rvore de hierarquia de views tela para renderizao, sua atividade deve chamar o mtodo setContentView() e passar uma referncia ao objeto n raiz. O sistema Android recebe esta referncia e usa-o para invalidar, medir e desenhar a rvore. O n raiz da hierarquia requisita que seus ns filhos desenhem a si prprios - por sua vez, cada n do ViewGroup responsvel por chamar cada um de seus views filhos para desenhar a si mesmos. Os filhos podem solicitar um tamanho e localizao com os pais, mas o objeto-me tem a deciso final sobre onde e qual o tamanho que cada criana pode ter. Android analisa os elementos do layout em ordem (a partir do topo da rvore de hierarquia), instanciando os Views e adicionando-os aos seus pais. Porque estes so desenhados em ordem, se h elementos que se sobrepem posies, o ltimo a ser elaborado vai ficar em cima dos outros previamente elaborados para aquele espao.

Como o Android desenha views


Quando uma atividade recebe o foco, ela ser convidada a desenhar o layout. O framework Android vai lidar com o processo de elaborao, mas a atividade deve apresentar o n raiz da sua hierarquia de layout. Desenho comea com o n raiz do layout. solicitado para medir e desenhar a rvore de layout. Desenho tratado pelo p da rvore e renderizao de cada vista que cruza a regio invlida. Por sua vez, cada grupo View responsvel por solicitar a cada um dos seus filhos a ser desenhado (com o mtodo draw()) e cada View responsvel pelo desenho de si. Como a rvore percorrida em ordem, isso significa que os pais sero desenhados antes do que seus filhos, com irmos elaborados na ordem em que aparecem na rvore.

ANDROID, uma viso geral Anderson Duarte de Amorim

109

Desenhar o layout um processo de duas passagens: a passagem de medidas e uma passagem de layout. A passagem de medio implementada com measure(int, int) e uma passagem top-down da rvore. Cada view empurra as especificaes de dimenso para baixo na rvore durante a recursividade. No final da passagem de medidas, cada View tem armazenado suas medidas. A segunda fase acontece no layout(int, int, int, int) e tambm top-down. Durante o passar, cada pai responsvel pelo posicionamento de todos os seus filhos usando os tamanhos computados na passagem de medidas. Durante um mtodo de retorno measure() da view, os valores getMeasuredWidth() e getMeasuredHeight() devem ser definidos, juntamente com as de todos os descendentes da view. Os valores de medio de largura e altura da view devem respeitar as restries impostas pelos pais da view. Isso garante que, no final da passagem de medidas, todos os pais aceitam todas as medies de seus filhos. Um pai view pode chamar measure() mais de uma vez sobre seus filhos. Por exemplo, os pais podem medir cada filho uma vez com dimenses no especificadas para descobrir o quo grande eles querem ser, ento chama measure() neles novamente com nmeros reais, se a soma dos tamanhos dos filhos irrestrita muito grande ou muito pequena (Ou seja, se os filhos no concordam entre si a respeito de quanto espao cada um ganha, o pai vai intervir e estabelecer as regras na segunda passagem). A passagem de medidas utiliza duas classes para comunicar dimenses. A classe
Para dar incio a um esquema, chamase requestLayout(). Este mtodo

View.MeasureSpec usada por views para contar aos pais como eles querem ser medidos e posicionados. A classe base LayoutParams apenas descreve quo grandes as views querem

normalmente chamado por uma view sobre si mesma quando se acredita que possvel no caber mais dentro de seus limites atuais.

ser para a largura e altura. Para cada dimenso, pode especificar um dos seguintes: um nmero exato FILL_PARENT, o que significa que o view quer ser to grande quanto seu pai (menos padding) WRAP_CONTENT, o que significa que o view quer ser grande o suficiente para colocar o seu contedo (mais padding).

ANDROID, uma viso geral Anderson Duarte de Amorim

110

H subclasses de LayoutParams para diferentes subclasses de ViewGroup. Por exemplo, RelativeLayout tem a sua prpria subclasse de LayoutParams, que inclui a capacidade de centralizar os filhos horizontalmente e verticalmente. MeasureSpecs so usados para empurrar os requisitos para baixo da rvore de pai para filho. Um MeasureSpec pode estar em um dos trs modos: NO ESPECIFICADO: Isto usado por um dos pais para determinar a dimenso desejada de um filho View. Por exemplo, um LinearLayout pode chamar measure() em seu filho com a altura indefinida e uma largura de exatamente 240. EXATAMENTE: Este usado pelos pais para impor um tamanho exato sobre a criana. A criana deve usar esse tamanho, e garante que todos os seus descendentes se encaixem dentro desse tamanho. NO MXIMO: Este usado pelos pais para impor um tamanho mximo para a criana. A criana deve garantir que ele e todos os seus descendentes vo caber dentro deste tamanho.

Layout
A maneira mais comum para definir o seu layout e expressar a hierarquia de view com um arquivo de layout XML. XML oferece uma estrutura legvel para o layout, muito parecido com HTML. Cada elemento em XML ou um View ou ViewGroup (ou descendentes dos mesmos). Objetos view so folhas da rvore, objetos ViewGroup so ramos da rvore. O nome de um elemento XML respectivo para a classe Java que representa. Assim, um elemento <TextView> cria um na sua interface do usurio, e um elemento <LinearLayout> cria um ViewGroup. Quando voc carregar um recurso de layout, o sistema Android inicializa esses objetos em tempo de execuo, correspondentes aos elementos em seu layout. Por exemplo, um layout simples vertical, com um text view e um boto parece com este:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"

ANDROID, uma viso geral Anderson Duarte de Amorim

111

android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>

Observe que o elemento LinearLayout contm o TextView e o Boto. Voc pode aninhar outro LinearLayout (ou outro tipo de grupo de exibio) aqui dentro, para alongar a hierarquia de view e criar um layout mais complexo. Dica: Voc tambm pode desenhar View e ViewGroups em cdigo Java, utilizando mtodos para inserir dinamicamente novos objetos View e ViewGroup. H uma variedade de maneiras em que voc pode formatar os seus view. Usando mais tipos diferentes de grupos de exibio, voc pode estruturar views herdados e view groups em um nmero infinito de maneiras. Alguns view groups pr-definidos oferecidas pelo Android (chamando layouts) incluem LinearLayout, RelativeLayout, TableLayout, GridLayout e outros. Cada um oferece um conjunto exclusivo de parmetros de layout que so usados para definir as posies das views herdadas e a estrutura de layout. To learn about some of the different kinds of view groups used for a layout, read . Para saber mais sobre alguns dos diferentes tipos de grupos de vista usado para um layout, leia os objetos de layout comum .

Widgets
Um widget um objeto View que serve como uma interface de interao com o usurio. Android fornece um conjunto de widgets plenamente implementadas, como botes, caixas de seleo, e os campos de entrada de texto, assim voc pode construir rapidamente sua interface do usurio. Alguns widgets fornecidos pelo Android so mais complexos, como um selecionador de data, um relgio, e controles de zoom. Mas voc no est limitado aos tipos de elementos fornecidos pela plataforma Android. Se voc quiser fazer algo mais personalizado e criar seus prprios elementos, pode, atravs da

ANDROID, uma viso geral Anderson Duarte de Amorim

112

definio de seu objeto View prprio ou atravs da extenso e combinao de elementos existentes.

ANDROID, uma viso geral Anderson Duarte de Amorim

113

Eventos UI
Uma vez que voc adicionou alguns views/widgets para a interface do usurio, voc provavelmente quer saber sobre a interao do usurio com eles, para que voc possa executar aes. Para ser informado de eventos de interface, voc precisa fazer uma de duas coisas: Definir um receptor de evento e registr-lo com a view. Muitas vezes, assim que voc vai receber os eventos. A classe View contm uma coleo de interfaces aninhadas nomeadas <something> Listener, cada um com um mtodo de retorno de chamada On <something>(). Por exemplo, View.OnClickListener (para lidar com os "cliques" na View), View.OnTouchListener (para lidar com eventos de tela de toque em uma exibio), e View.OnKeyListener (para lidar com teclas pressionadas no dispositivo dentro de uma View). Ento se voc quer sua View para ser notificado quando ela "clicada" (como quando um boto selecionado), implemente OnClickListener e defina o seu mtodo de retorno onClick() (onde voc executar a ao aps o clique), e registra-o para a View com setOnClickListener(). Substituir um mtodo de retorno existente para a View. Isto o que voc deve fazer quando voc implementou sua prpria classe View e quer receber eventos especficos que ocorrem dentro dele. Exemplificando eventos voc pode manipular incluso quando a tela tocada (onTouchEvent()), quando o trackball movido (onTrackballEvent()), ou quando uma tecla no dispositivo pressionada (onKeyDown()). Isso permite que voc defina o comportamento padro para cada evento dentro da sua View personalizada e determinar se o evento deve ser transmitido para alguma outra View filho. Novamente, essas so chamadas de retorno para a classe View, assim, sua nica chance de defini-los quando voc cria um componente personalizado.

Menus
Os menus de aplicativos so outra parte importante da interface do usurio de um aplicativo. Menus oferecem uma interface confivel, que revela funes de aplicativos e configuraes. O menu de aplicativos mais comuns revelado, pressionando a tecla MENU no dispositivo. No entanto, voc tambm pode adicionar menus de contexto,

ANDROID, uma viso geral Anderson Duarte de Amorim

114

que podem ser revelados quando o usurio pressiona e mantm pressionado em um item. Os menus tambm so estruturados usando uma hierarquia View, mas voc no define essa estrutura por si mesmo. Em vez disso, voc define mtodos de retorno como onCreateOptionsMenu() ou onCreateContextMenu() para a sua atividade, e declara os itens que voc deseja incluir em seu menu. Em momento oportuno, o Android ir criar automaticamente a necessria hierarquia View para o menu e desenhar cada um dos seus itens de menu na mesma. Menus tambm lidam com seus prprios eventos, por isso no h necessidade de registrar eventos listeners sobre os itens do seu menu. Quando um item no seu menu selecionado, o mtodo onOptionsItemSelected() ou onContextItemSelected() ser chamado pelo framework. E, assim como o layout do aplicativo, voc tem a opo de declarar os itens para seu menu em um arquivo XML.

Tpicos Avanados
Uma vez que voc aprendeu os fundamentos da criao de uma interface, voc pode explorar algumas caractersticas avanadas para a criao de uma interface de aplicao mais complexa.

Adaptadores
s vezes voc deseja preencher um view group com algumas informaes que no podem ser codificados, em vez disso, voc quer associar a sua view a uma fonte externa de dados. Para fazer isso, use um AdapterView como seu grupo de viso e cada filho view inicializado e preenchido com os dados do adaptador. O objeto AdapterView uma implementao do ViewGroup que determina as views dos filhos com base em um determinado adaptador. O adaptador funciona como um mensageiro entre a fonte de dados (talvez um array de strings externa) e os AdapterView, que exibe. Existem vrias implementaes da classe Adapter, para tarefas especficas, como a CursorAdapter para leitura de dados banco de dados de um cursor ou um ArrayAdapter para a leitura de uma matriz arbitrria.

ANDROID, uma viso geral Anderson Duarte de Amorim

115

Estilos e Temas
Talvez voc no esteja satisfeito com a aparncia dos widgets padro. Para rev-los, voc pode criar alguns dos seus prprios estilos e temas. Um estilo um conjunto de um ou mais atributos de formatao que voc pode aplicar como uma unidade de elementos individuais em seu layout. Por exemplo, voc pode definir um estilo que especifica um determinado tamanho de texto e cor, em seguida, aplic-lo apenas a elementos especficos. Um tema um conjunto de um ou mais atributos de formatao que voc pode aplicar como uma unidade para todas as atividades em uma aplicao, ou apenas uma atividade nica. Por exemplo, voc pode definir um tema que define as cores especficas para a moldura da janela e o fundo do painel, e define o tamanho dos textos e cores dos menus. Este tema pode ser aplicado a atividades especficas ou todo o aplicativo. Estilos e temas so recursos. Android oferece alguns recursos de estilo padro e tema que voc pode usar, ou voc pode declarar o seu prprio estilo customizado e recursos de tema.

ANDROID, uma viso geral Anderson Duarte de Amorim

116

Declarando Layout
Seu layout a arquitetura para interface de usurio em uma atividade. Ela define a estrutura de layout e possui todos os elementos que aparecem para o usurio. Voc pode declarar o seu layout de duas maneiras: Declare elementos UI em XML - Android fornece um vocabulrio XML simples que corresponde s classes View e subclasses, tais como widgets e layouts. Instanciar elementos de layout em tempo de execuo - O aplicativo pode criar objetos de View e ViewGroup (e manipular suas propriedades) de forma programaticamente. O framework Android lhe d a flexibilidade para usar um ou ambos os mtodos para declarar e gerenciar a interface do usurio do seu aplicativo. Por exemplo, voc poderia declarar layouts padro de seu aplicativo em XML, incluindo os elementos da tela que aparecero nela e suas propriedades. Voc pode ento adicionar o cdigo em seu aplicativo que iria alterar o estado dos objetos da tela, incluindo aqueles declarados em XML, em tempo de execuo. A vantagem de declarar a sua interface em XML que ela permite melhor separar a apresentao da sua aplicao do cdigo que controla o seu comportamento. Suas descries de interface do usurio so externas sua aplicao, o que significa que voc pode modific-lo ou adapt-lo sem ter que modificar seu cdigofonte e recompilar. Por exemplo, voc pode criar layouts de tela de XML para
O plugin ADT para Eclipse oferece um preview do seu layout XML - com o arquivo XML aberto, selecione a guia Layout. Voc tambm deve tentar a ferramenta de Hierarquia Viewer para depurao de layouts ela revela propriedade de layout, desenha wireframes e com view indicadores completas

padding/margin

renderizadas enquanto voc depurar no emulador ou dispositivo. A ferramenta layoutopt permite analisar rapidamente os seus layouts e hierarquias de ineficincias ou outros problemas.

orientaes diferentes dispositivo,

diferentes, tela do

tamanhos e

lnguas

diferentes.

Alm disso, declarar o layout em XML torna mais fcil visualizar a estrutura de sua

ANDROID, uma viso geral Anderson Duarte de Amorim

117

interface do usurio, por isso mais fcil depurar problemas. Como tal, este documento centra-se em ensin-lo a declarar o seu layout em XML. Se voc estiver interessado em instanciar objetos view em tempo de execuo, consulte as classes ViewGroup e View. Em geral, o vocabulrio XML para a declarao de elementos da interface segue de perto a estrutura e nomenclatura das classes e mtodos, onde os nomes dos elementos correspondem aos nomes de classes e nomes de atributos correspondem aos mtodos. De fato, a correspondncia muitas vezes to direta que voc pode adivinhar o atributo XML corresponde a um mtodo de classe, ou adivinhar o que a classe corresponde a um determinado elemento XML. No entanto, note que nem todo vocabulrio idntico. Em alguns casos, existem ligeiras diferenas de nomenclatura. Por exemplo, o elemento EditText tem um atributo text que corresponde a EditText.setText() . Dica: Saiba mais sobre os diferentes tipos de layout em Common Layout Objects.

Escreve o XML
Usando o vocabulrio do Android XML, voc pode rapidamente criar layouts de interface do usurio e os elementos de tela que eles contm, da mesma forma que voc cria pginas web em HTML - com uma srie de elementos aninhados. Cada arquivo de layout deve conter exatamente um elemento de raiz, que deve ser um objeto de view ou ViewGroup. Depois de definir o elemento raiz, voc pode adicionar objetos de layout adicionais ou widgets como elementos filho para criar gradualmente uma hierarquia de exibio que define o layout. Por exemplo, aqui est um esquema XML que usa um LinearLayout vertical que contm um TextView e um Button :
<?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" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>

ANDROID, uma viso geral Anderson Duarte de Amorim

118

Depois de ter declarado o seu layout em XML, salve o arquivo com a extenso .xml em seu projeto Android no diretrio res/layout/, assim ele vai compilar corretamente.

Carregar os recursos XML


Quando voc compilar sua aplicao, cada arquivo de layout XML compilado em um View de recurso. Voc deve carregar o recurso de layout de sua aplicao, em sua implementao de retorno Activity.onCreate(). Faa isso chamando setContentView(), passando a referncia ao seu recurso de layout na forma de: R.layout. layout_file_name. Por exemplo, se o seu layout XML salvo como main_layout.xml, voc deve carreg-lo para a sua atividade da seguinte forma:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }

O mtodo de retorno onCreate() em sua atividade chamado pelo framework Android quando sua atividade lanada.

Atributos
Cada objeto View e ViewGroup apia a sua prpria variedade de atributos XML. Alguns atributos so especficos para um objeto View (por exemplo, TextView apia o atributo textSize), mas esses atributos tambm so herdadas por qualquer objetos View que podem estender esta classe. Alguns so comuns a todos objetos View, porque eles so herdados da classe View raiz (como o atributo id). E, outros atributos so considerados "parmetros de layout", que so atributos que descrevem determinadas orientaes de layout do objeto View.

ID
Qualquer objeto View pode ter um ID de inteiro associado a ele, para identificar o View dentro da rvore. Quando o aplicativo compilado, essa identificao referenciada como um inteiro, mas a identificao normalmente atribuda no layout do arquivo XML como uma string, no atributo id. Este um atributo XML comum a todos os objetos View (definido pela classe View) e voc vai us-lo muitas vezes. A sintaxe para uma identificao, dentro de uma tag XML :

ANDROID, uma viso geral Anderson Duarte de Amorim

119

android:id="@+id/my_button"

O smbolo de arroba (@) no incio da string indica que o analisador XML deve analisar e ampliar o resto da seqncia de identificao e identific-lo como um recurso de identificao. O sinal de mais (+) significa que este um novo nome de recurso que deve ser criado e adicionado aos nossos recursos (no arquivo R.java). H uma srie de recursos de outro tipo de identificao que so oferecidos pela estrutura do Android. Ao fazer referncia a uma identificao de recurso Android, voc no precisa do sinal de mais, mas deve adicionar o namespace de pacote android, assim:
android:id="@android:id/empty"

Com o namespace de pacote android no lugar, agora estamos fazendo referncia a uma ID da classe de recursos android.R, ao invs da classe de recursos locais. A fim de criar views e referenci-los a partir da aplicao, um padro comum : 1. Definir uma view/widget no arquivo de layout e atribuir um ID nico:
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>

2. Em seguida, crie uma instncia do objeto view e capture-o a partir do layout (geralmente no mtodo onCreate()):
Button myButton = (Button) findViewById(R.id.my_button);

Definir os IDs dos objetos view importante ao criar um RelativeLayout. Em um RelativeLayout, views irmos podem definir a sua disposio em relao a outro view irmo, que referenciada pela ID exclusiva. Uma identificao no precisa ser nica para toda a rvore, mas deve ser exclusiva dentro da parte da rvore que voc est procurando (o que pode muitas vezes ser a rvore inteira, por isso melhor ser completamente original quando possvel).

Parmetros de layout
Atributos de layout XML chamados layout_something definem os parmetros de layout para a view que sejam adequadas para a ViewGroup em que ele reside.

ANDROID, uma viso geral Anderson Duarte de Amorim

120

Cada

classe

ViewGroup

implementa

uma

classe

aninhada

que

estende

ViewGroup.LayoutParams. Esta subclasse contm os tipos de propriedades que definem o tamanho e a posio de cada view filha, conforme apropriado para o view group. Como voc pode ver na figura 1, o grupo de exibio pai define os parmetros de layout para cada view filho (incluindo o view group dos filhos).

Figura 1. Visualizao de uma hierarquia de views com os parmetros de layout associado a cada exibio.

Note que cada subclasse LayoutParams tem sua prpria sintaxe para definir valores. Cada elemento filho deve definir LayoutParams que so apropriadas para seu pai, embora possa tambm definir LayoutParams diferentes para seus filhos. Todos os view groups incluem uma largura e altura (layout_width e layout_height), e cada view necessria para defini-los. Muitos LayoutParams tambm incluem margens opcional e fronteiras. Voc pode especificar a largura e altura com medidas exatas, embora voc provavelmente no ir querer fazer isso com freqncia. Mais freqentemente, voc vai usar uma dessas constantes para definir a largura ou altura: wrap_content diz a seu view a arranjar a si prprio para as dimenses exigidas pelo seu contedo.

ANDROID, uma viso geral Anderson Duarte de Amorim

121

fill_parent (rebatizada match_parent na API Nvel 8) diz sua view para se tornar to grande quanto o view group dos pais ir permitir. Em geral, especificar uma largura de layout e altura, utilizando unidades absolutas, tais como pixels no recomendada. Em vez disso, por meio de medidas como a densidade relativa independente unidades de pixel (DP), wrap_content ou fill_parent, uma abordagem melhor, porque ajuda a garantir que seu aplicativo ir exibir corretamente atravs de uma variedade de tamanhos de tela do dispositivo. Os tipos de medio aceitos so definidos no documento Recursos Disponveis.

Posio de Layout
A geometria de uma view a de um retngulo. Uma view tem uma localizao, expresso como um par de coordenadas esquerda e superior, e duas dimenses, expressa em uma largura e uma altura. A unidade para a localizao e as dimenses o pixel. possvel recuperar o local de uma viso chamando os mtodos getLeft() e getTop(). O primeiro retorna a esquerda, ou X, de coordenadas do retngulo que representa o view. O segundo retorna o topo, ou Y, coordenadas do retngulo que representa o view. Estes dois mtodos devolvem o local da view em relao ao seu pai. Por exemplo, quando o Getleft() retorna 20, significa que o ponto de vista est localizado a 20 pixels para a direita da borda esquerda da sua controladora direta. Alm disso, vrios mtodos de convenincia so oferecidos para evitar clculos desnecessrios, ou seja, getRight() e getBottom(). Esses mtodos retornam as coordenadas das bordas direita e inferior do retngulo que representa o view. Por exemplo, chamando getRight() semelhante ao seguinte clculo: getLeft() + getWidth().

Tamanho, padding e margin


O tamanho de uma view expressa com uma largura e uma altura. Uma viso realmente possue dois pares de valores de largura e altura. O primeiro par conhecido como largura medida e altura medida. Essas dimenses definem quo grande quer ser em vista de seu pai. As dimenses medidas podem ser obtidas chamando getMeasuredWidth() e getMeasuredHeight().

ANDROID, uma viso geral Anderson Duarte de Amorim

122

O segundo par conhecido simplesmente como largura e altura, ou s vezes a largura de desenho e altura de desenho. Essas dimenses definem o tamanho real do view sobre tela, em tempo de desenho e depois de layout. Esses valores podem ser, mas no tem que ser diferentes da largura e altura medidos. A largura e altura podem ser obtidas chamando getWidth() e getHeight(). Para medir as suas dimenses, uma view leva em conta o seu preenchimento. O preenchimento expresso em pixels para as partes esquerda, superior, direita e inferior do view. Padding pode ser utilizado para compensar o contedo da viso de uma determinada quantidade de pixels. Por exemplo, um padding-left de 2 vai empurrar o contedo do view por 2 pixels direita da margem esquerda. Padding pode ser definido usando o mtodo setPadding(int, int, int, int) e consultado chamando getPaddingLeft(), getPaddingTop(), getPaddingRight() e getPaddingBottom(). Apesar de uma exibio poder definir um padding, isso no prev qualquer apoio para as margens. No entanto, view groups prestam esse apoio.

ANDROID, uma viso geral Anderson Duarte de Amorim

123

Criando Menus
Os menus so uma parte importante da interface de uma atividade do usurio, que fornecem aos usurios uma forma familiar para executar aes. Android oferece um quadro simples para voc adicionar menus padro para seu aplicativo. Existem trs tipos de menus de aplicao:

Menu de Opes
A coleo de itens do menu principal para uma atividade, que aparece quando o usurio toca no boto MENU. Quando o aplicativo est rodando o Android 3.0 ou posterior, voc pode fornecer acesso rpido para selecionar itens de menu, colocando-os diretamente na barra de ao, como "itens de ao."

Menu de Contexto
Uma lista de itens de menu flutuante que aparece quando o usurio toca e tem uma viso que est registrada para fornecer um menu de contexto.

Submenu
Uma lista de itens de menu flutuante que aparece quando o usurio toca um item de menu que contm um menu aninhado.

Criando um recurso de menu


Em vez de instanciar um Menu no seu cdigo do aplicativo, voc deve definir um menu e todos os seus itens em um XML menu resource, em seguida, inflar o recurso de menu (carreg-lo como um objeto programvel) no seu cdigo do aplicativo. Utilizando um recurso de menu para definir o seu menu uma boa prtica, pois separa o contedo do menu de seu cdigo do aplicativo. tambm mais fcil de visualizar a estrutura e o contedo de um menu em XML. Para criar um recurso de menu, crie um arquivo XML dentro de seu projeto do diretrio res/menu/ e crie o menu com os seguintes elementos:

ANDROID, uma viso geral Anderson Duarte de Amorim

124

<menu> Define um Menu, que um recipiente para itens de menu. Um elemento

<menu> deve ser o n raiz para o arquivo e pode conter um ou mais <item> e elementos <group>. <item> Cria um MenuItem, o que representa um nico item em um menu. Este elemento pode conter um elemento <menu> aninhado, a fim de criar um submenu. <group> Um opcional, recipiente invisvel para elementos <item>. Ele permite que voc categorize itens de menu para que compartilhe as propriedades tais como estado ativo e visibilidade. Aqui est um exemplo de menu chamado game_menu.xml:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/new_game" android:icon="@drawable/ic_new_game" android:title="@string/new_game" /> <item android:id="@+id/help" android:icon="@drawable/ic_help" android:title="@string/help" /> </menu>

Este exemplo define um menu com dois itens. Cada item inclui os atributos: android:id A identificao do recurso que nico para o item, que permite que o aplicativo possa reconhecer o item quando o usurio seleciona-o. android:icon Uma referncia para um desenho para usar como cone do item. android:title Uma referncia a uma string para usar como ttulo do item.

ANDROID, uma viso geral Anderson Duarte de Amorim

125

H muito mais atributos que voc pode incluir em um <item>, incluindo alguns que especificam como o item pode aparecer na barra de ao.

Inflar um recurso de menu


A partir de seu cdigo de aplicativo, voc pode inflar um recurso de menu (converter o recurso de XML em um objeto programvel) utilizando MenuInflater.inflate(). Por exemplo, o seguinte cdigo infla o arquivo game_menu.xml definido acima, durante o mtodo de retorno onCreateOptionsMenu(), para usar o menu como a atividade do Menu de Opes:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; }

O mtodo getMenuInflater() retorna uma MenuInflater para a atividade. Com este objetivo, voc pode chamar inflate(),que infla um recurso de menu em um objeto Menu. Neste exemplo, o recurso de menu definido por game_menu.xml inflado no Menu que foi passado para onCreateOptionsMenu().

Criando um Menu de Opes


Quando executado em um dispositivo com Android 2.3 e inferior, o Menu de Opes aparece na parte inferior da tela, como mostrado na figura 1. Quando aberto, a primeira poro visvel do Menu de Opes o menu do cone. Ele mantm os seis primeiros itens do menu. Se voc adicionar mais de seis itens do Menu de Opes, o Android coloca o sexto item e aqueles aps no menu de estouro, que o usurio pode abrir tocando no item "More" do menu.

Figura 1. Screenshot do menu de opes no browser.

ANDROID, uma viso geral Anderson Duarte de Amorim

126

No Android 3.0 e superior, os itens do Menu de Opes so colocados na barra de ao, que aparece no topo da atividade no lugar da barra de ttulo tradicional. Por padro todos os itens do Menu de Opes so colocados no menu de estouro, que o usurio pode abrir ao tocar no cone do menu no lado direito da barra de ao. No entanto, voc pode colocar itens de menu diretamente na Barra de ao como "itens de ao", para acesso instantneo, como mostrado na figura 2.

Figura 2. Imagem da barra de ao na aplicao de e-mail, com dois itens de ao do Menu de Opes, alm do menu de estouro.

Quando o sistema Android cria o Menu de Opes, pela primeira vez, ele chama o mtodo onCreateOptionsMenu() da sua atividade. Substituir este mtodo em sua atividade e preencher o Menu que passado para o mtodo, Menu inflando um recurso de menu como descrito acima em Inflating a Menu Resource. Por exemplo:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; }

Voc tambm pode preencher o menu em cdigo, usando add() para adicionar itens ao Menu. Nota: No Android 2.3 e inferiores, o sistema chama onCreateOptionsMenu() para criar o menu de opes quando o usurio abre pela primeira vez, mas no Android 3.0 e superior, o sistema cria assim que a atividade criada, a fim e preencher a barra de ao.

Respondendo ao do usurio
Quando o usurio seleciona um item de menu do Menu de Opes (incluindo itens de ao na barra de ao), o sistema chama o mtodo onOptionsItemSelected() da sua atividade. Este mtodo passa o MenuItem que o usurio selecionou. Voc pode identificar o item de menu chamando getItemId(), que retorna o ID nico para o item de menu (definido pelo atributo android:id no recurso de menu ou com um nmero inteiro

ANDROID, uma viso geral Anderson Duarte de Amorim

127

dado ao mtodo add()). Voc pode combinar esta identificao contra itens do menu conhecidos e executar a ao apropriada. Por exemplo:
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.new_game: newGame(); return true; case R.id.help: showHelp(); return true; default: return super.onOptionsItemSelected(item); } }

Neste exemplo, getItemId() consulta o ID do item de menu selecionado e o comando switch compara o ID contra os IDs de recursos que foram atribudos aos itens do menu no recurso XML. Quando um switch case manipula o item de menu, ela retorna true para indicar que a seleo de item foi tratada. Caso contrrio, a declarao padro passa o item de menu para a super classe, no caso dele poder lidar com o item selecionado. (Se voc diretamente estendeu a classe Activity, ento, a super classe retorna false, mas uma boa prtica passar itens de menu no tratados para a classe super em vez de diretamente retornar false). Alm disso, o Android 3.0 adiciona a capacidade de definir o comportamento de clicar em um item de menu no menu de recursos XML, usando o atributo android:onClick. Ento voc no precisa implementar onOptionsItemSelected(). Usando o atributo android:onClick, voc pode especificar um mtodo a ser chamado quando o usurio seleciona o item de menu. Sua atividade deve, ento, aplicar o mtodo especificado no android:onClick para que ele aceite um nico MenuItem de parmetro, quando o sistema chama este mtodo, ele passa o item de menu selecionado. Dica: Se seu aplicativo contm atividades mltiplas e algumas delas oferecem o mesmo Menu de Opes, considere a criao de uma atividade que no executa nada, exceto os mtodos onCreateOptionsMenu() e onOptionsItemSelected(). Em seguida, estenda esta classe para cada atividade que deve compartilhar o mesmo menu de opes. Dessa forma, voc tem que gerenciar apenas um conjunto de cdigo para manipular aes de menu e cada classe descendente herda o comportamento do menu.

ANDROID, uma viso geral Anderson Duarte de Amorim

128

Se voc quiser adicionar itens de menu para um dos descendentes de suas atividades, sobreponha onCreateOptionsMenu() nessa atividade. Chame

super.onCreateOptionsMenu(menu) para que os itens do menu inicial sejam criados, em seguida, adicione novos itens de menu com menu.add(). Voc tambm pode substituir o comportamento da super classe para os itens de menu individuais.

Alterando os itens de menu em tempo de execuo


Uma vez que a atividade criada, o mtodo onCreateOptionsMenu() chamado apenas uma vez, como descrito acima. O sistema mantm e re-utiliza o Menu que voc define neste mtodo at que sua atividade seja destruda. Se voc quiser mudar o menu de opes a qualquer momento aps ter sido criado pela primeira vez, voc deve substituir o mtodo onPrepareOptionsMenu(). Isto lhe passa o objeto Menu como ele existe atualmente. Isso til se voc quiser remover, adicionar, desativar ou ativar itens de menu, dependendo do estado atual de sua aplicao. No Android 2.3 e inferiores, o sistema chama onPrepareOptionsMenu() cada vez que o usurio abre o Menu de Opes. No Android 3.0 e superior, voc deve chamar invalidateOptionsMenu() quando voc desejar atualizar o menu, porque o menu est sempre aberto. O sistema ir ento chamar onPrepareOptionsMenu(), assim voc pode atualizar os itens de menu. Nota: Voc nunca deve alterar itens no menu de opes com base no View atualmente em foco. Quando estiver no modo de toque (quando o usurio no estiver usando um trackball ou d-pad), views podem no ter foco, ento voc nunca deve usar o foco como base para a modificao de itens do Menu de Opes. Se voc quiser fornecer itens de menu que so sensveis ao contexto para uma View, use um menu de contexto. Se voc est desenvolvendo para o Android 3.0 ou superior, no se esquea de ler tambm Usando a Barra de Ao.

Criando um Menu de Contexto


Um menu de contexto conceitualmente semelhante ao menu exibido quando o usurio executa um "clique-direito" em um PC. Voc deve usar um menu de contexto para proporcionar ao usurio o acesso s aes que pertencem a um item especfico na ANDROID, uma viso geral Anderson Duarte de Amorim

129

interface do usurio. No Android, um menu de contexto exibido quando o usurio executa um "toque longo" (pressiona e segura) em um item. Voc pode criar um menu de contexto para qualquer view, apesar de menus de contexto serem mais freqentemente utilizados para os itens em um ListView. Quando o usurio pressiona longamente em um item em uma ListView e a lista est registrada para fornecer um menu de contexto, o item da lista sinaliza para o usurio que um menu de contexto est disponvel animando sua cor de fundo, que faz a transio do laranja ao branco antes de abrir o menu de contexto. (O aplicativo Contatos demonstra esta caracterstica.) A fim de fornecer um menu de contexto, voc deve "registrar" a view de um menu de contexto. Chame

Registre uma ListView


Se a sua atividade usa um ListView e voc deseja que todos os itens da lista forneam um menu de contexto, registre todos os itens de um menu de contexto, passando o ListView para registerForContextMenu(). Por exemplo, se voc estiver usando uma ListActivity, registre todos os itens da lista

registerForContextMenu() e passe a View que voc quer dar um menu de contexto. Quando esta view receber um toque de longa durao, ela exibe um menu de contexto. Para definir a aparncia e comportamento do menu de contexto, substitua seus mtodos de retorno do menu de contexto

como esta:
registerForContextMenu( getListView() );

da atividade, onCreateContextMenu() e onContextItemSelected(). Por exemplo, aqui est um onCreateContextMenu() que usa o recurso de menu context_menu.xml:
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); }

MenuInflater usado para inflar o menu de contexto de um recurso de menu. (Voc tambm pode usar o add() para adicionar itens de menu). Os parmetros de mtodo de retorno incluem o View que o usurio selecionou e ContextMenu.ContextMenuInfo que

ANDROID, uma viso geral Anderson Duarte de Amorim

130

fornece informaes adicionais sobre o item selecionado. Voc pode usar esses parmetros para determinar qual menu de contexto deve ser criado, mas neste exemplo, todos os menus de contexto para a atividade so os mesmos. Ento, quando o usurio seleciona um item no menu de contexto, o sistema chama onContextItemSelected(). Aqui est um exemplo de como voc pode manipular os itens selecionados:
@Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); switch (item.getItemId()) { case R.id.edit: editNote(info.id); return true; case R.id.delete: deleteNote(info.id); return true; default: return super.onContextItemSelected(item); } }

A estrutura deste cdigo semelhante ao exemplo de criao de um Menu de Opes, em que getItemId() consulta o ID do item de menu selecionado e um switch corresponde ao item para as identificaes que so definidos no recurso de menu. E como o exemplo do menu de opes, a declarao padro chama a super classe no caso dela poder lidar com itens de menu no tratados aqui, se necessrio. Neste exemplo, o item selecionado um item da ListView. Para executar uma ao sobre o item selecionado, o aplicativo precisa saber o ID da lista para o item selecionado (a sua posio no ListView). Para obter o ID, o aplicativo chama getMenuInfo(), que retorna um objeto AdapterView.AdapterContextMenuInfo que inclui a identificao de lista para o item selecionado no campo id. Os mtodos locais editNote() e deleteNote() aceitam essa identificao da lista para executar uma ao nos dados especificados pelo ID da lista. Nota: Os itens em um menu de contexto no suportam cones ou teclas de atalho.

ANDROID, uma viso geral Anderson Duarte de Amorim

131

Criando Submenus
Um submenu um menu que o usurio pode abrir por selecionar um item em outro menu. Voc pode adicionar um submenu a qualquer menu (com exceo de um submenu). Submenus so teis quando seu aplicativo tem um monte de funes que podem ser organizadas em tpicos, como os itens na barra de uma aplicao para PC de menu (Arquivo, Editar, Exibir, etc.) Ao criar o seu recurso de menu, voc pode criar um submenu, adicionando um elemento <menu> como o filho de um <item>. Por exemplo:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/file" android:icon="@drawable/file" android:title="@string/file" > <!-- "file" submenu --> <menu> <item android:id="@+id/create_new" android:title="@string/create_new" /> <item android:id="@+id/open" android:title="@string/open" /> </menu> </item> </menu>

Quando o usurio seleciona um item do submenu, o respectivo mtodo de retorno onitem-selected do menu pai recebe o evento. Por exemplo, se o menu acima aplicado como um Menu de Opes, ento o mtodo onOptionsItemSelected() chamado quando um item de submenu selecionado. Voc tambm pode usar addSubMenu() para adicionar dinamicamente um SubMenu a um Menu j existente. Isso retorna o novo objeto SubMenu, para o qual voc pode adicionar itens de submenu, usando add().

Outras funes do menu


Aqui esto algumas outras caractersticas que podem ser aplicadas a itens do menu.

Grupos de Menu
Um grupo de menu uma coleo de itens de menu que compartilham certas caractersticas.

ANDROID, uma viso geral Anderson Duarte de Amorim

132

Com um grupo, voc pode: Mostrar ou ocultar todos os itens com setGroupVisible() Ativar ou desativar todos os itens com setGroupEnabled() Especificar se todos os itens so verificados com setGroupCheckable() Voc pode criar um grupo aninhando elementos <item> dentro de um elemento <group> em seu recurso de menu ou pela especificao de um ID de grupo com o mtodo add(). Aqui est um exemplo de recurso de menu que inclui um grupo:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/item1" android:icon="@drawable/item1" android:title="@string/item1" /> <!-- menu group --> <group android:id="@+id/group1"> <item android:id="@+id/groupItem1" android:title="@string/groupItem1" /> <item android:id="@+id/groupItem2" android:title="@string/groupItem2" /> </group> </menu>

Os itens que esto no grupo aparecem da mesma forma que o primeiro item que no est em um grupo - todos os trs itens no menu so irmos. No entanto, voc pode modificar as caractersticas dos dois elementos do grupo, referenciando o ID do grupo e utilizando os mtodos listados acima.

Itens de menu verificados


Um menu pode ser til como uma interface fazendo das opes ativas e inativas, usando uma caixa de seleo para as opes de stand-alone, ou radion buttons para grupos com opes mutuamente exclusivas. A Figura 2 mostra um submenu com os itens que so verificados com radio buttons.

Figura 3. Screenshot de um submenu com os itens verificados.

ANDROID, uma viso geral Anderson Duarte de Amorim

133

Nota: Os itens de menu no menu de cone (no menu Opes) no podem exibir uma caixa de seleo ou radio button. Se voc optar por fazer os itens no menu do cone selecionveis, voc deve manualmente indicar o estado marcado por trocar o cone e/ou texto cada vez que ocorrem as mudanas de estado. Voc pode definir o comportamento checkable para itens individuais de menu usando o atributo android:checkable no elemento <item>, ou para um grupo inteiro com o atributo android:checkableBehavior no elemento <group>. Por exemplo, todos os itens deste grupo de menu so verificados com um boto de rdio:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/red" android:title="@string/red" /> <item android:id="@+id/blue" android:title="@string/blue" /> </group> </menu>

O atributo android:checkableBehavior aceita tanto: single Apenas um item do grupo pode ser verificado (botes de rdio) all Todos os itens podem ser verificados (caixas) none Nenhum item pode ser verificado Voc pode aplicar um estado padro verificado de um item usando o atributo android:checked no elemento <item> e alter-lo em cdigo com o mtodo setChecked(). Quando um item checkable selecionado, o sistema chama o seu mtodo de retorno item-selected (como onOptionsItemSelected()). aqui que voc deve definir o estado da caixa, pois um boto de opo ou de rdio no muda o seu estado automaticamente.

ANDROID, uma viso geral Anderson Duarte de Amorim

134

Voc pode consultar o estado atual do item (como era antes que o usurio selecionou) com isChecked() e, em seguida, definir o estado de verificado com setChecked(). Por exemplo:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.vibrate: case R.id.dont_vibrate: if (item.isChecked()) item.setChecked(false); else item.setChecked(true); return true; default: return super.onOptionsItemSelected(item); } }

Se voc no definir o estado de verificado dessa forma, o estado visvel do item (a caixa de seleo ou boto de rdio) no vai mudar quando o usurio selecion-lo. Quando voc definir o estado, a atividade preserva o estado de verificado do item para que quando o usurio abra o menu mais tarde, o estado de verificado que voc definiu esteja visvel. Nota: os itens de menu verificveis se destinam a serem usados apenas em uma sesso base e no sero salvos aps a aplicao ser destruda. Se voc tiver as configuraes do aplicativo que voc gostaria de salvar para o usurio, voc deve armazenar os dados usando Preferncias Compartilhadas.

As teclas de atalho
Para facilitar o acesso rpido aos itens do menu de opes quando o dispositivo do usurio tem um teclado fsico, voc pode adicionar atalhos de acesso rpido usando letras e/ou nmeros, com os atributos android:alphabeticShortcut e

android:numericShortcut no elemento <item>. Voc tambm pode usar os mtodos setAlphabeticShortcut(char) e setNumericShortcut(char). Teclas de atalho no so case sensitive. Por exemplo, se voc aplicar o caractere "s" como um atalho alfabtico para um item "salvar" de menu, ento quando o menu est aberto (ou quando o usurio segura o boto MENU) e o usurio pressiona a tecla "s", o item "Salvar" selecionado.

ANDROID, uma viso geral Anderson Duarte de Amorim

135

Esta tecla de atalho exibida como uma dica no item de menu, abaixo do nome do item de menu (com exceo de itens no menu do cone, que so exibidas somente se o usurio segura o boto MENU). Nota: as teclas de atalho para itens de menu s funcionam em dispositivos com um teclado de hardware. Atalhos no podem ser adicionado a itens de um menu de contexto.

Adicionar intenes em menu dinamicamente


s vezes voc quer um item de menu para iniciar uma atividade usando uma Intent (seja uma atividade em seu aplicativo ou outro aplicativo). Quando voc sabe a inteno que voc deseja usar e tem um item de menu especfico que deve iniciar a inteno, voc pode executar a inteno com startActivity() durante o apropriado mtodo de retorno on-item-selected (como o callback onOptionsItemSelected()). No entanto, se voc no tiver certeza de que o dispositivo do usurio contm um aplicativo que lida com a inteno, ento adicionar um item de menu que chama isso pode resultar em um item de menu que no funciona, porque a inteno pode no resolver a uma atividade. Para resolver isso, Android permite a voc adicionar dinamicamente os itens do menu para o menu quando Android encontra atividades sobre o dispositivo que lidam com sua inteno. Para adicionar itens de menu baseado em atividades disponveis que aceitam uma inteno: 1. Definir uma inteno, com a categoria CATEGORY_ALTERNATIVE e/ou CATEGORY_SELECTED_ALTERNATIVE, exigncias. 2. Chamar Menu.addIntentOptions(). Android ento procura todas as aplicaes que podem executar a inteno e adiciona-os ao seu menu. Se no houver aplicativos instalados que satisfazem a inteno, ento no h itens de menu que sejam adicionados. alm de quaisquer outras

ANDROID, uma viso geral Anderson Duarte de Amorim

136

Nota: CATEGORY_SELECTED_ALTERNATIVE usada para segurar o elemento selecionado atualmente na tela. Assim, ele s deve ser utilizado para a criao de um menu em onCreateContextMenu(). Por exemplo:
@Override public boolean onCreateOptionsMenu(Menu menu){ super.onCreateOptionsMenu(menu); // Create an Intent that describes the requirements to fulfill, to be included // in our menu. The offering app must include a category value of Intent.CATEGORY_ALTERNATIVE. Intent intent = new Intent(null, dataUri); intent.addCategory(Intent.CATEGORY_ALTERNATIVE); // Search and populate the menu with acceptable offering applications. menu.addIntentOptions( R.id.intent_group, // Menu group to which new items will be added 0, // Unique item ID (none) 0, // Order for the items (none) this.getComponentName(), // The current activity name null, // Specific items to place first (none) intent, // Intent created above that describes our requirements 0, // Additional flags to control items (none) null); // Array of MenuItems that correlate to specific items (none) return true; }

Para cada atividade descoberta que fornece uma inteno de filtro correspondente a inteno definida um item de menu adicionado, utilizando o valor na inteno do filtro android:label como o ttulo do item de menu e o cone do aplicativo como o item cone do menu. O mtodo addIntentOptions() retorna o nmero de itens de menu que foram acrescentados. Nota: Quando voc chamar addIntentOptions(), ela substitui qualquer e todos os itens do menu, o grupo de menu especificado no primeiro argumento.

Permitindo a sua atividade a ser adicionada para outros menus


Voc tambm pode oferecer os servios de sua atividade para outras aplicaes, para que seu aplicativo possa ser includo no menu de outros (inverter os papis descritos acima).

ANDROID, uma viso geral Anderson Duarte de Amorim

137

Para ser includo em outros menus de aplicativos, voc precisa definir uma inteno de filtro, como de costume, mas e/ou no se esquea de incluir o

CATEGORY_ALTERNATIVE

CATEGORY_SELECTED_ALTERNATIVE

para o filtro de categoria intenes. Por exemplo:


<intent-filter label="Resize Image"> ... <category android:name="android.intent.category.ALTERNATIVE" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> ... </intent-filter>

Leia mais sobre como escrever filtros de inteno em Intents and Intents Filters.

ANDROID, uma viso geral Anderson Duarte de Amorim

138

Usando a barra de ao
A barra de ao um widget para atividades que substitui a tradicional barra de ttulo no topo da tela. Por padro, a barra de ao inclui o logotipo da aplicao do lado esquerdo, seguido do ttulo da atividade, e todos os itens disponveis no menu Opes no lado direito. A Barra de ao oferece vrios recursos teis, incluindo a capacidade de: Exibir itens do Menu de Opes diretamente na Barra de ao, como "itens de ao" - fornecendo acesso imediato s aes-chave dos usurios. Os itens de menu que no aparecem como itens de ao so colocados no menu de estouro, revelado por uma lista suspensa na barra de aes. Fornecer as guias para navegar entre os fragmentos. Fornea uma lista drop-down para a navegao. Fornecer interativas "vises de ao" no lugar de itens de ao (como uma caixa de pesquisa).

Figura 1. Uma imagem da barra de ao na aplicao de e-mail, contendo itens de ao para compor novo email e atualizar a caixa de entrada.

Adicionando a barra de ao
A barra de ao includa por padro em todas as atividades que visam o Android 3.0 ou superior. Mais especificamente, todas as atividades que usam o novo tema "hologrfico" incluem a barra de ao, e qualquer aplicao que tem como alvo o Android 3.0 automaticamente recebe esse tema. Uma aplicao considerada para "o alvo" Android 3.0 quando definido tanto o atributo android:minSdkVersion ou android:targetSdkVersion no elemento <uses-sdk> para "11" ou superior. Por exemplo:

ANDROID, uma viso geral Anderson Duarte de Amorim

139

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloworld" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /> <application ... > ... </application> </manifest>

Neste exemplo, a aplicao requer uma verso mnima do API Nvel 4 (Android 1.6), mas tambm atinge API Nvel 11 (Android 3.0). Dessa forma, quando o aplicativo instalado em um dispositivo rodando Android 3.0 ou superior, o sistema aplica o tema hologrfico para cada atividade, e assim, cada atividade inclui a Barra de Aes. No entanto, se voc quiser usar APIs de Barra de Aes, tais como guias para adicionar ou modificar estilos da barra de ao, voc precisa definir o android:minSdkVersion para "11", assim voc pode acessar a classe ActionBar.

Removendo a barra de ao
Se voc quiser remover a barra de ao para uma determinada atividade, defina o tema da atividade para Theme.Holo.NoActionBar. Por exemplo:
<activity android:theme="@android:style/Theme.Holo.NoActionBar">

Dica: Se voc tem um tema de atividade personalizado no qual voc gostaria de remover a barra de ao, defina a propriedade de estilo android:windowActionBar false. Voc tambm pode ocultar a barra de ao em tempo de execuo chamando hide(), e depois mostr-la novamente chamando show(). Por exemplo:
ActionBar actionBar = getActionBar(); actionBar.hide();

Quando a barra de ao se esconde, o sistema ajusta seu contedo das atividades para preencher todo o espao disponvel na tela. Nota: Se voc remover a Barra de ao usando um tema, a janela no vai permitir a barra de ao a todos, ento voc no pode adicion-la em tempo de execuo chamar getActionBar() ir retornar null.

ANDROID, uma viso geral Anderson Duarte de Amorim

140

Adicionando itens de ao
Um item de ao que simplesmente um item do menu de opes que voc declara deve aparecer diretamente na barra de aes. Um item de ao pode incluir um cone e/ou texto. Se um item de menu no aparece como um item de ao, o sistema coloca no menu de estouro, que o usurio pode abrir com o cone do menu no lado direito da barra de ao.

Figura 2. Uma barra de ao com dois itens de ao e menu de estouro.

Quando a primeira atividade comea, o sistema preenche a barra de ao e menu de estouro chamando onCreateOptionsMenu() para sua atividade. Conforme discutido no guia para a criao de menus, neste mtodo callback que voc define o menu de opes para a atividade. Voc pode especificar um item de menu para aparecer como um item de ao, se no houver espao para isso, a partir do seu recurso de menu, declarando android:showAsAction="ifRoom" para o elemento <item>. Desta forma, o item de menu aparece na barra de ao para um acesso rpido apenas se houver espao disponvel para ele. Se no houver espao suficiente, o item colocado no menu de transbordamento (revelado pelo cone do menu no lado direito da barra de ao). Voc tambm pode declarar um item de menu para aparecer como um item de ao a partir do seu cdigo de aplicativo, chamando setShowAsAction() no MenuItem e passando SHOW_AS_ACTION_IF_ROOM. Se o item de menu fornece tanto um ttulo como um cone, ento o item de ao mostra apenas o cone por default. Se voc quiser incluir o texto do item de ao, adicione a flag "with text": em XML, adicionar withText para o atributo android:showAsAction ou, no cdigo do aplicativo, use a flag SHOW_AS_ACTION_WITH_TEXT ao chamar setShowAsAction(). A Figura 2 mostra uma barra de ao que tem dois itens de ao com o texto e o cone para o menu de estouro. Aqui est um exemplo de como voc pode declarar um item de menu como um item de ao em um arquivo de recurso de menu:

ANDROID, uma viso geral Anderson Duarte de Amorim

141

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_add" android:icon="@drawable/ic_menu_save" android:title="@string/menu_save" android:showAsAction="ifRoom|withText" /> </menu>

Neste caso, tanto as flags ifRoom e withText esto definidas, de modo que quando este item aparece como um item de ao, inclui o texto do ttulo, juntamente com o cone. Um item de menu colocado na barra de ao dispara os mesmos mtodos de callback que outros itens do menu de opes. Quando o usurio seleciona um item de ao, sua atividade recebe uma chamada para onOptionsItemSelected(), passando o ID do item. Nota: Se voc adicionou o item de menu de um fragmento, o respectivo mtodo onOptionsItemSelected() chamado para esse fragmento. No entanto, a atividade tem a chance de manipul-lo primeiro, ento o sistema chama onOptionsItemSelected() da atividade antes de chamar o fragmento. Voc tambm pode declarar um item que sempre aparece como um item de ao, mas voc deve evitar faz-lo, porque ele pode criar uma interface confusa se houver muitos itens de ao e tambm podem colidir com outros elementos na barra de aes.

Usando o cone do aplicativo como um item de ao


Por padro, o cone do aplicativo aparece na barra de aes, no lado esquerdo. Ele tambm responde interao do usurio (quando o usurio toca, ele responde visualmente do mesmo jeito que os itens de ao) e que sua responsabilidade fazer algo quando o usurio toca-os.

Figura 3. Barra de ao de email, com o cone do aplicativo no lado esquerdo.

O comportamento deve ser normal para a sua aplicao para regressar "HOME" atividade ou ao estado inicial (como quando a atividade no mudou, mas os fragmentos foram alterados) quando o usurio toca o cone. Se o usurio j est em casa ou no estado inicial, ento voc no precisa fazer nada.

ANDROID, uma viso geral Anderson Duarte de Amorim

142

Quando o usurio toca o cone, o sistema chama o mtodo onOptionsItemSelected() de sua atividade com o ID android.R.id.home. Ento, voc precisa adicionar uma condio para o seu mtodo onOptionsItemSelected() para receber android.R.id.home e executar a ao apropriada, como iniciar a atividade inicial ou remover recentes transaes do fragmento fora da pilha. Se voc responder para o cone do aplicativo, retornando atividade inicial, voc deve incluir o flag FLAG_ACTIVITY_CLEAR_TOP na Intent. Com este indicador, se a atividade que voc est comeando j existe na tarefa atual, ento todas as atividades em cima dela so destrudas e essa trazida para frente. Voc deve favorecer essa abordagem, porque ir para "HOME" uma ao que equivalente a "voltar atrs" e voc geralmente no deve criar uma nova instncia da atividade inicial. Caso contrrio, voc pode acabar com uma longa pilha de atividades na tarefa atual. Por exemplo, aqui est uma implementao do onOptionsItemSelected() que retorna para a aplicao da "HOME" de atividade:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // app icon in Action Bar clicked; go home Intent intent = new Intent(this, HomeActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; default: return super.onOptionsItemSelected(item); } }

Usando o cone do aplicativo para navegar "para cima"


Voc tambm pode usar o cone do aplicativo para oferecer uma navegao "para cima" para o usurio. Isto especialmente til quando o aplicativo composto por atividades que geralmente aparecem em uma certa ordem e se pretende facilitar a habilidade do usurio para navegar na hierarquia de atividade.

A maneira como voc responde a este evento a mesma de quando navegando para HOME (como discutido acima, exceto se voc iniciar uma atividade diferente, com base ANDROID, uma viso geral Anderson Duarte de Amorim

143

na atividade corrente). Tudo que voc precisa fazer para indicar ao usurio que o comportamento diferente definir a barra de ao para "mostrar a HOME como para cima". Voc pode fazer isso chamando setDisplayHomeAsUpEnabled(true) na barra de aes da sua atividade. Quando o fizer, o sistema retira o cone do aplicativo com uma seta indicando o comportamento para cima, como mostrado acima. Por exemplo, aqui est como voc pode mostrar o cone do aplicativo como uma ao "para cima":
@Override protected void onStart() { super.onStart(); ActionBar actionBar = this.getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); }

Ento, sua atividade deve responder ao usurio tocar no cone, a partir do onOptionsItemSelected(), recebendo o ID android.R.id.home (como mostrado acima). Neste caso, ao navegar para cima, ainda mais importante que voc use o FLAG_ACTIVITY_CLEAR_TOP na Intent, de modo que voc no cria uma nova instncia da atividade do pai, se j existe um.

Adicionando uma exibio de ao

Figura 5. Uma viso de ao com um widget SearchView.

Uma exibio de ao um widget que aparece na barra de ao como um substituto para um item de ao. Por exemplo, se voc tem um item no menu opes para "Busca", voc pode adicionar uma exibio de ao para o item que fornece um widget SearchView na barra de ao sempre que o item ativado como um item de ao. Ao adicionar uma viso de ao para um item de menu, importante que voc ainda permita ao item se comportar como um item de menu normal quando ela no aparece na barra de aes. Por exemplo, um item de menu para realizar uma pesquisa deve, por padro, abrir a janela de pesquisa do Android, mas se o item colocado na barra de ao, a viso de ao aparece com um widget SearchView. A Figura 5 mostra um exemplo do SearchView em uma viso de ao.

ANDROID, uma viso geral Anderson Duarte de Amorim

144

A melhor forma de declarar uma viso de ao para um item est em seu recurso de menu, usando o atributo android:actionLayout ou android:actionViewClass: O valor para android:actionLayout deve ser um ponteiro de recurso para um arquivo de layout. Por exemplo:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_search" android:title="Search" android:icon="@drawable/ic_menu_search" android:showAsAction="ifRoom" android:actionLayout="@layout/searchview" /> </menu>

O valor para android:actionViewClass deve ser um nome de classe qualificado para o View que voc deseja usar. Por exemplo:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_search" android:title="Search" android:icon="@drawable/ic_menu_search" android:showAsAction="ifRoom" android:actionViewClass="android.widget.SearchView" /> </menu>

Voc deve incluir android:showAsAction="ifRoom" para que o item aparea como uma viso de ao quando o room est disponvel. Se necessrio, no entanto, pode forar o item que sempre aparea como uma viso de ao, definindo android:showAsAction para "always". Agora, quando o item de menu exibido como um item de ao, esta vista de ao aparece em vez do cone e/ou texto do ttulo. No entanto, se no houver espao suficiente na barra de ao, o item aparece no menu de estouro como um item de menu normal e voc deve responder a ela a partir do mtodo de retorno

onOptionsItemSelected(). Quando a primeira atividade comea, o sistema preenche a barra de ao e menu de estouro chamando onCreateOptionsMenu(). Depois de ter inflado seu menu neste mtodo, voc pode adquirir elementos em uma viso de ao (talvez a fim de anexar ouvintes) chamando findItem() com o ID do item de menu, ento getActionView() no

ANDROID, uma viso geral Anderson Duarte de Amorim

145

MenuItem retornado. Por exemplo, o widget de busca do modelo acima adquirido como este:
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options, menu); SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); // Set appropriate listeners for searchView ... return super.onCreateOptionsMenu(menu); }

Adicionando abas

Figura 6. Screenshot de abas na barra de ao, do modelo de aplicao do Honeycomb Gallery.

A Barra de ao pode exibir guias que permitem ao usurio navegar entre diferentes fragmentos na atividade. Cada guia pode incluir um ttulo e/ou um cone. Para comear, o esquema deve incluir um View, em que cada Fragment associado com uma guia exibida. Tenha certeza de que tem uma identificao que pode ser usada para fazer referncia a ela em seu cdigo. Para adicionar guias para a barra de aes: 1. Criar uma aplicao de ActionBar.TabListener para manipular os eventos de interao na barra de guias de ao. Voc deve implementar todos os mtodos: onTabSelected(), onTabUnselected(), e onTabReselected(). Cada mtodo de retorno passa a ActionBar.Tab que recebeu o evento e um FragmentTransaction para voc efetuar as transaes do fragmento (adicionar ou remover fragmentos).

ANDROID, uma viso geral Anderson Duarte de Amorim

146

Por exemplo:
private class MyTabListener implements ActionBar.TabListener { private TabContentFragment mFragment; // Called to create an instance of the listener when adding a new tab public TabListener(TabContentFragment fragment) { mFragment = fragment; } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment_content, mFragment, null); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(mFragment); } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // do nothing } }

Esta implementao de ActionBar.TabListener adiciona um construtor que salva o Fragment associado com um guia para que cada retorno possa adicionar ou remover esse fragmento. 2. Receba a ActionBar para a sua atividade, chamando getActionBar() de sua atividade, durante onCreate() (mas no se esquea de fazer isso depois de voc ter chamado setContentView()). 3. Chame setNavigationMode(NAVIGATION_MODE_TABS) para habilitar o modo guia para a ActionBar . 4. Criar cada guia para a barra de ao: a. Criar uma nova ActionBar.Tab chamando newTab() na ActionBar . b. Acrescentar o texto do ttulo e/ou um cone para o guia, chamando setText() e/ou setIcon(). Dica: Esses mtodos retornam a mesma instncia ActionBar.Tab, assim voc pode encadear as chamadas juntas.

ANDROID, uma viso geral Anderson Duarte de Amorim

147

c. Declare o ActionBar.TabListener para usar a guia por meio de um exemplo de sua aplicao para setTabListener(). 5. Adicione cada ActionBar.Tab barra de ao, chamando addTab() na ActionBar e passe a ActionBar.Tab. Por exemplo, o cdigo a seguir combina as etapas 2-5 para criar duas guias e adicionlas Barra de ao:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // setup Action Bar for tabs final ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // remove the activity title to make space for tabs actionBar.setDisplayShowTitleEnabled(false); // instantiate fragment for the tab Fragment artistsFragment = new ArtistsFragment(); // add a new tab and set its title text and tab listener actionBar.addTab(actionBar.newTab().setText(R.string.tab_artists) .setTabListener(new TabListener(artistsFragment))); Fragment albumsFragment = new AlbumsFragment(); actionBar.addTab(actionBar.newTab().setText(R.string.tab_albums) .setTabListener(new TabListener(albumsFragment))); }

Todos os comportamentos que ocorrem quando uma guia selecionada devem ser definidos pelo seu mtodo de callback ActionBar.TabListener. Quando uma guia selecionada, ela recebe uma chamada para onTabSelected() e a que voc deve adicionar o fragmento apropriado para a exibio designada em seu layout, utilizando add() com o previsto FragmentTransaction. Da mesma forma, quando uma guia desmarcada (porque outra guia selecionada), voc deve remover o fragmento do layout, utilizando remove(). Ateno: Voc no deve chamar commit() para essas operaes, o sistema chama-o para voc e pode lanar uma exceo se voc cham-lo. Voc tambm no pode adicionar essas transaes de fragmento para o fundo da pilha. Se a sua atividade interrompida, voc deve manter a guia selecionada no momento com o estado salvo de modo que quando o usurio retorna sua aplicao, voc pode ANDROID, uma viso geral Anderson Duarte de Amorim

148

abrir a guia. Quando hora de salvar o estado, voc pode consultar a atual guia selecionada com getSelectedNavigationIndex(). Isso retorna a posio do ndice da guia selecionada. Ateno: importante que voc salve o estado de cada fragmento quando necessrio, pois quando o usurio alterna fragmentos com as guias, e em seguida, retorna a um fragmento anterior, aparece o caminho que ele deixou. Para obter informaes sobre como salvar o seu estado de fragmento, consulte o guia do desenvolvedor sobre Fragmentos.

Adicionando de navegao drop-down


Como um outro modo de navegao em sua atividade, voc pode fornecer uma lista suspensa na barra de aes. Por exemplo, a lista drop-down pode fornecer os meios alternativos para classificar o contedo da atividade ou mudar a conta do usurio. Aqui est uma lista rpida de medidas para permitir a navegao drop-down: 1. Criar um SpinnerAdapter que fornece a lista de itens selecionveis para o dropdown e a disposio para usar ao desenhar cada item na lista. 2. Implementar ActionBar.OnNavigationListener para definir o comportamento quando o usurio seleciona um item da lista. 3. Habilitar o modo de navegao para a barra de ao com setNavigationMode(). Por exemplo:
ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

Nota: Voc deve executar isto durante a sua atividade do mtodo onCreate(). 4. Em seguida, defina o retorno para a lista drop-down com

setListNavigationCallbacks(). Por exemplo:


actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);

Este mtodo tem a sua SpinnerAdapter e ActionBar.OnNavigationListener. Essa a configurao bsica. No entanto, a implementao da SpinnerAdapter e ActionBar.OnNavigationListener onde a maioria do trabalho feito. H muitas

ANDROID, uma viso geral Anderson Duarte de Amorim

149

maneiras que voc pode aplicar isto para definir a funcionalidade para o seu drop-down de navegao e implementar vrios tipos de SpinnerAdapter alm do escopo deste documento (voc deve referenciar para a classe SpinnerAdapter para obter mais informaes). No entanto, abaixo h um exemplo simples para um SpinnerAdapter e ActionBar.OnNavigationListener para voc comear.

Exemplo de SpinnerAdapter e OnNavigationListener


SpinnerAdapter um adaptador que fornece dados para um widget spinner, como a lista drop-down na barra de aes. SpinnerAdapter uma interface que voc pode implementar, mas Android inclui algumas implementaes teis que voc pode estender, como ArrayAdapter e SimpleCursorAdapter. Por exemplo, aqui est uma maneira fcil de criar um SpinnerAdapter usando a implementao de ArrayAdapter, que usa uma matriz de string como fonte de dados:
SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list, android.R.layout.simple_spinner_dropdown_item);

O mtodo createFromResource() usa trs parmetros: a aplicao Context, a identificao de recursos para array de string, e o layout a ser usado para cada item da lista. Um array de string definido em um recurso parecido com este:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="action_list"> <item>Mercury</item> <item>Venus</item> <item>Earth</item> </string-array> </pre>

O ArrayAdapter retornado por createFromResource() est completo e pronto para voc passar a setListNavigationCallbacks() (na etapa 4 acima). Antes de fazer, porm, voc precisa criar o OnNavigationListener. A implementao do ActionBar.OnNavigationListener onde voc lida com as mudanas de fragmento ou outras modificaes sua atividade quando o usurio seleciona um item da lista drop-down. H apenas um mtodo callback para implementar o receptor: onNavigationItemSelected().

ANDROID, uma viso geral Anderson Duarte de Amorim

150

O mtodo onNavigationItemSelected() recebe a posio do item na lista e um ID de nico item fornecido pela SpinnerAdapter. Aqui est um exemplo que instancia uma implementao annima de

OnNavigationListener, que insere um Fragment dentro do recipiente layout identificado por R.id.fragment_container:
mOnNavigationListener = new OnNavigationListener() { // Get the same strings provided for the drop-down's ArrayAdapter String[] strings = getResources().getStringArray(R.array.action_list); @Override public boolean onNavigationItemSelected(int position, long itemId) { // Create new fragment from our own Fragment class ListContentFragment newFragment = new ListContentFragment(); FragmentTransaction ft = openFragmentTransaction(); // Replace whatever is in the fragment container with this fragment // and give the fragment a tag name equal to the string at the position selected ft.replace(R.id.fragment_container, newFragment, strings[position]); // Apply changes ft.commit(); return true; } };

Esta instncia de OnNavigationListener est completo e agora voc pode chamar setListNavigationCallbacks() (na etapa 4), passando o ArrayAdapter e este OnNavigationListener. Neste exemplo, quando o usurio seleciona um item da lista drop-down, um fragmento adicionado ao layout (que substitui o fragmento atual no R.id.fragment_container vista). O fragmento adicional dada uma etiqueta que identifica-lo, que a mesma seqncia de caracteres usado para identificar o fragmento na lista drop-down.

ANDROID, uma viso geral Anderson Duarte de Amorim

151

Aqui est um olhar da classe ListContentFragment que define cada fragmento neste exemplo:
public class ListContentFragment extends Fragment { private String mText; @Override public void onAttach(Activity activity) { // This is the first callback received; here we can set the text for // the fragment as defined by the tag specified during the fragment transaction super.onAttach(activity); mText = getTag(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // This is called to define the layout for the fragment; // we just create a TextView and set its text to be the fragment tag TextView text = new TextView(getActivity()); text.setText(mText); return text; } }

Estilizando a barra de ao
A barra de ao o ttulo do seu aplicativo e um ponto de interao primrio para os usurios, ento voc pode querer modificar alguns em seu projeto, a fim de torn-lo sentir mais integrado com o design do aplicativo. H vrias maneiras que voc pode fazer isso se quiser. Para modificaes simples para o ActionBar, voc pode usar os mtodos a seguir: setBackgroundDrawable() Define um drawable para usar como fundo da barra de ao. O drawable deve ser uma imagem Nine-patch, uma forma, ou uma cor slida, para que o sistema pode redimensionar a drawable com base no tamanho da barra de ao (voc no deve usar uma imagem bitmap de tamanho fixo). setDisplayUseLogoEnabled() Permite o uso de uma imagem alternativa (a "logo") na barra de ao, em vez do cone do aplicativo padro. Um logotipo muitas vezes uma imagem mais ampla, mais detalhada que representa a aplicao. Quando isso estiver ativado, o ANDROID, uma viso geral Anderson Duarte de Amorim

152

sistema utiliza a imagem do logotipo definido para a aplicao (ou a atividade individual) no arquivo de manifesto, com o atributo android:logo. O logotipo ser redimensionado, conforme necessrio para ajustar a altura da barra de ao. (Melhores prticas projetar o logotipo com o mesmo tamanho do cone do aplicativo.) Para personalizaes mais complexas, voc pode usar estilos e temas do Android para remodelar sua barra de ao de vrias maneiras. A Barra de ao tem dois temas padro, "dark" e "light". O tema escuro aplicado com o tema padro hologrfico, conforme especificado pelo tema Theme.Holo. Se voc quiser um fundo branco com texto escuro, em vez disso, voc pode aplicar o tema Theme.Holo.Light para a atividade no arquivo de manifesto. Por exemplo:
<activity android:name=".ExampleActivity" android:theme="@android:style/Theme.Holo.Light" />

Para ter mais controle, voc pode substituir o tema Theme.Holo ou Theme.Holo.Light e aplicar estilos personalizados para determinados aspectos da Barra de Aes. Algumas das propriedades da barra de ao voc pode personalizar incluindo o seguinte: android:actionBarTabStyle Estilo de abas na barra de ao. android:actionBarTabBarStyle Estilo para a barra que aparece abaixo das abas na barra de ao. android:actionBarTabTextStyle Estilo para o texto nos separadores. android:actionDropDownStyle Estilo para a lista drop-down utilizado para o menu de navegao de transbordamento e drop-down. android:actionButtonStyle Estilo para a imagem de fundo usado para os botes na barra de ao.

ANDROID, uma viso geral Anderson Duarte de Amorim

153

Por exemplo, aqui est um arquivo de recurso que define um tema personalizado para a barra de ao, baseado no tema padro Theme.Holo:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- the theme applied to the application or activity --> <style name="CustomActionBar" parent="android:style/Theme.Holo.Light"> <item name="android:actionBarTabTextStyle">@style/customActionBarTabTextStyle</item> <item name="android:actionBarTabStyle">@style/customActionBarTabStyle</item> <item name="android:actionBarTabBarStyle">@style/customActionBarTabBarStyle</item> </style> <!-- style for the tab text --> <style name="customActionBarTabTextStyle"> <item name="android:textColor">#2966c2</item> <item name="android:textSize">20sp</item> <item name="android:typeface">sans</item> </style> <!-- style for the tabs --> <style name="customActionBarTabStyle"> <item name="android:background">@drawable/actionbar_tab_bg</item> <item name="android:paddingLeft">20dp</item> <item name="android:paddingRight">20dp</item> </style> <!-- style for the tab bar --> <style name="customActionBarTabBarStyle"> <item name="android:background">@drawable/actionbar_tab_bar</item> </style> </resources>

Nota: Para que a imagem de fundo guia mude, dependendo do estado de separador atual (selecionado, pressionado, no selecionado), o recurso drawable utilizado deve ser uma lista de estado drawable. Tambm certo que o tema declara um tema principal, da qual ele herda todos os estilos no explicitamente declarados em seu tema. Voc pode aplicar o seu tema personalizado para o aplicativo inteiro ou para atividades individuais no arquivo de manifesto, como este:
<application android:theme="@style/CustomActionBar" ... />

Alm disso, se voc quer criar um tema personalizado para a sua atividade que remove a barra de ao completamente, use os atributos de estilo a seguir:

ANDROID, uma viso geral Anderson Duarte de Amorim

154

android:windowActionBar Defina esta propriedade de estilo como false para remover a barra de aes. android:windowNoTitle Defina esta propriedade de estilo como true tambm para remover a barra de ttulo tradicional.

ANDROID, uma viso geral Anderson Duarte de Amorim

155

Criando caixas de dilogo


Uma caixa de dilogo geralmente uma pequena janela que aparece na frente da atividade atual. A atividade em causa perde o foco e o dilogo aceita todas as interaes do usurio. Os dilogos so normalmente utilizados para as notificaes que devem interromper o usurio e para executar tarefas curtas que se relacionam diretamente com a aplicao em curso (como uma barra de progresso ou um prompt de login). A classe Dialog a classe base para a criao de dilogos. No entanto, voc geralmente no deve instanciar um Dialog diretamente. Em vez disso, voc deve usar uma das seguintes subclasses: AlertDialog Uma caixa de dilogo que pode gerenciar zero, um, dois ou trs botes, e/ou uma lista de itens selecionveis que podem incluir caixas de verificao ou botes de rdio. O AlertDialog capaz de construir a maioria das interfaces de dilogo com o usurio e o tipo de caixa de dilogo sugerido. ProgressDialog Uma caixa de dilogo que exibe uma roda de progresso ou barra de progresso. Porque uma extenso do AlertDialog, ele tambm suporta botes. DatePickerDialog Um dilogo que permite que o usurio selecione uma data. TimePickerDialog Um dilogo que permite ao usurio selecionar um tempo. Se voc quiser personalizar a sua prpria caixa de dilogo, voc pode estender a base Dialog ou qualquer objeto das subclasses acima e definir um novo layout.

Mostrando uma caixa de dilogo


Um dilogo sempre criado e exibido como parte de uma Activity. Voc normalmente deve criar dilogos de dentro do mtodo de retorno onCreateDialog(int) da sua atividade. Quando voc usa esta chamada, o sistema Android gerencia automaticamente

ANDROID, uma viso geral Anderson Duarte de Amorim

156

o estado de cada dilogo e os ganchos para a atividade, efetivamente tornando-o o "dono" de cada dilogo. Como tal, cada dilogo herda algumas propriedades da atividade. Por exemplo, quando uma janela aberta, a tecla Menu revela o menu de opes definidas para a atividade e as teclas de volume modificam o fluxo de udio usado pela atividade. Nota: Se voc decidir criar um dilogo fora do mtodo onCreateDialog(), no ir ser anexado a uma atividade. Voc pode, entretanto, anex-lo a uma atividade com setOwnerActivity(Activity). Quando voc quer mostrar uma janela, chame showDialog(int) e passe um nmero inteiro que identifica a caixa de dilogo que voc deseja exibir. Quando uma janela solicitada pela primeira vez, o Android chama

onCreateDialog(int) de sua atividade, que onde voc deve criar uma instncia do Dialog. Neste mtodo de retorno passado o mesmo ID que voc passou para showDialog(int). Depois de criar o dilogo, retorne o objeto no final do mtodo. Antes que o dilogo ser exibido, o Android tambm chama o mtodo callback opcional onPrepareDialog(int, Dialog). Defina nesse mtodo se voc deseja alterar as propriedades da caixa de dilogo cada vez que for aberta. Este mtodo chamado toda vez que uma caixa de dilogo aberta, enquanto onCreateDialog(int) chamado apenas na primeira vez que uma caixa de dilogo aberta. Se voc no definir onPrepareDialog(), ento o dilogo continuar a ser o mesmo que era o tempo anterior que foi aberto. Este mtodo tambm passa o ID do dilogo, alm de um dilogo do objeto que voc criou na onCreateDialog(). A melhor maneira de definir os mtodos de retorno onCreateDialog(int) e onPrepareDialog(int, Dialog) com uma instruo switch que verifica o parmetro id que passado para o mtodo. Cada caso deve verificar se h uma identificao nica de dilogo e, em seguida, criar e definir o respectivo dilogo. Por exemplo, imagine um jogo que usa dois dilogos distintos: um para indicar que o jogo tem uma pausa e outra para indicar que o jogo acabou. Primeiro, defina um ID de nmero inteiro para cada caixa de dilogo:
static final int DIALOG_PAUSED_ID = 0; static final int DIALOG_GAMEOVER_ID = 1;

ANDROID, uma viso geral Anderson Duarte de Amorim

157

Em seguida, defina a chamada onCreateDialog(int) com um caso de interruptor para cada ID:
protected Dialog onCreateDialog(int id) { Dialog dialog; switch(id) { case DIALOG_PAUSED_ID: // do the work to define the pause Dialog break; case DIALOG_GAMEOVER_ID: // do the work to define the game over Dialog break; default: dialog = null; } return dialog; }

Nota: Neste exemplo, no h nenhum cdigo dentro da declarao de caso, porque o procedimento para a definio de seu dilogo est fora do escopo desta seo. Quando hora de mostrar um dos dilogos, chame showDialog(int) com o ID de um dilogo:
showDialog(DIALOG_PAUSED_ID);

Dispensar um dilogo
Quando estiver pronto para fechar o dilogo, voc pode descart-lo chamando dismiss() no objeto Dialog. Se necessrio, voc tambm pode chamar dismissDialog(int) da atividade, o que efetivamente chama dismiss() na caixa de dilogo para voc. Se voc estiver usando onCreateDialog(int) para gerir o seu estado de dilogos (como discutido na seo anterior), ento cada vez que o dilogo indeferido, o estado do objeto de dilogo mantido pela atividade. Se voc decidir que voc no precisa mais desse objeto ou importante que o estado esteja limpo, ento voc deve chamar removeDialog(int). Isto ir remover todas as referncias internas ao objeto e se o dilogo est mostrando, vai dispens-lo.

Usando demisso de receptores


Se voc quiser que seu aplicativo execute alguns procedimentos no momento em que um dilogo dispensado, ento voc deve anexar um receptor on-dismiss no seu dilogo. ANDROID, uma viso geral Anderson Duarte de Amorim

158

Primeiro defina a interface DialogInterface.OnDismissListener. Essa interface possui apenas um mtodo, onDismiss(DialogInterface), que ser chamado quando o dilogo for descartado. Depois, passe a sua implementao OnDismissListener para setOnDismissListener(). No entanto, note que os dilogos tambm podem estar "cancelados". Este um caso especial que indica que o dilogo foi explicitamente cancelado por parte do usurio. Isso ocorrer se o usurio pressiona o boto "BACK " para fechar a janela, ou se a caixa de dilogo solicita explicitamente cancel() (talvez a partir de um boto "Cancelar" na caixa de dilogo). Quando um dilogo for cancelado, o OnDismissListener ainda ser notificado, mas se voc gostaria de ser informado de que o dilogo foi expressamente cancelado (e no dispensado normalmente), ento voc deve registrar um DialogInterface.OnCancelListener com setOnCancelListener().

Criando um AlertDialog
Um AlertDialog uma extenso da classe Dialog. capaz de construir a maioria das interfaces de usurio de dilogo e o tipo de dilogo sugerido. Voc deve us-lo para o dilogo que usam qualquer uma das seguintes caractersticas: Um ttulo Uma mensagem de texto Um, dois ou trs botes Uma lista de itens selecionveis (com checkbox ou radio-button) Para criar um AlertDialog, use a subclasse AlertDialog.Builder. Receba um construtor com AlertDialog.Builder(Context) e depois use os mtodos pblicos de classe para definir todas as propriedades AlertDialog. Depois que est finalizado com o construtor, recupere o objeto AlertDialog com create(). Os tpicos a seguir mostram como definir vrias propriedades do AlertDialog usando a classe AlertDialog.Builder. Se voc usar qualquer um dos seguintes cdigos de exemplo dentro do seu mtodo de retorno onCreateDialog(), voc pode retornar o objeto resultante de dilogo para exibir o dilogo.

ANDROID, uma viso geral Anderson Duarte de Amorim

159

Adicionando botes

Para criar um AlertDialog com botes lado a lado, como a mostrada na imagem direita, use o mtodo set...Button():
AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MyActivity.this.finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create();

Primeiro, adicione uma mensagem para o dilogo com setMessage(CharSequence) . Ento, comece mtodo de encadeamento e definir a janela para no ser cancelado (por isso o usurio no poder fechar o dilogo com o boto traseiro) com setCancelable(boolean) . Para cada boto, use um dos set...Button() mtodos, como setPositiveButton() , que aceita o nome do boto e um DialogInterface.OnClickListener que define as medidas a tomar quando o usurio seleciona o boto. Nota: Voc s pode adicionar um boto de cada tipo AlertDialog. Ou seja, voc no pode ter mais de um boto "positivo". Isso limita o nmero de botes possveis para trs: positivo, neutro e negativo. Estes nomes so tecnicamente irrelevantes para a funcionalidade real de seus botes, mas deve ajud-lo a acompanhar o que faz o qu.

ANDROID, uma viso geral Anderson Duarte de Amorim

160

Adicionando uma lista

Para criar um AlertDialog com uma lista de itens selecionveis como o mostrado esquerda, use o mtodo setItems():
final CharSequence[] items = {"Red", "Green", "Blue"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Pick a color"); builder.setItems(items, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show(); } }); AlertDialog alert = builder.create();

Primeiro, adicione um ttulo para o dilogo com setTitle(CharSequence). Em seguida, adicione uma lista de itens selecionveis com setItems(), que aceita um conjunto de itens a serem exibidos e um DialogInterface.OnClickListener que define as medidas a tomar quando o usurio seleciona um item.

Adicionando caixas de seleo e botes de rdio


Para criar uma lista de itens de escolha mltipla (caixas) ou itens de escolha nica (botes de rdio) dentro do dilogo, e use os mtodos

setMultiChoiceItems()

setSingleChoiceItems(),

respectivamente. Se voc criar uma destas listas selecionveis no mtodo de retorno onCreateDialog(), o Android gerencia o estado da lista para voc. Contanto que a atividade esteja ativa, o dilogo se lembra dos itens que foram previamente selecionados, mas quando o usurio sai da atividade, a seleo est perdida.

ANDROID, uma viso geral Anderson Duarte de Amorim

161

Nota: Para salvar a seleo quando o usurio deixa ou faz pausa na atividade, voc deve salvar e restaurar corretamente a configurao de todo o ciclo de vida de atividade. Para salvar permanentemente as selees, mesmo quando o processo de atividade completamente parado, voc precisa salvar as configuraes com uma das tcnicas de Armazenamento de Dados. Para criar um AlertDialog com uma lista de itens de escolha simples, como a mostrada acima, use o mesmo cdigo do exemplo anterior, mas substitua o mtodo setItems() pelo setSingleChoiceItems():
final CharSequence[] items = {"Red", "Green", "Blue"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Pick a color"); builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show(); } }); AlertDialog alert = builder.create();

O segundo parmetro no mtodo setSingleChoiceItems() um valor inteiro para o checkedItem, que indica a posio de lista com base zero do item selecionado padro. Use "-1" para indicar que nenhum item deve ser selecionado por padro.

Criar um ProgressDialog
A ProgressDialog uma extenso da classe AlertDialog que pode exibir uma animao de progresso na forma de uma roda, para uma tarefa com o progresso indefinido, ou uma barra de progresso, para uma tarefa que tem uma progresso definida. O dilogo tambm pode fornecer botes, como um de cancelar um download. Abrir uma janela de progresso pode ser to simples como chamar

ProgressDialog.show(). Por exemplo, o dilogo mostrado acima pode ser facilmente alcanado sem gerenciar o dilogo atravs da chamada onCreateDialog(int), conforme mostrado abaixo: ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "", "Loading. Please wait...", true);

ANDROID, uma viso geral Anderson Duarte de Amorim

162

O primeiro parmetro a aplicao Context, o segundo um ttulo para o dilogo (vazio), o terceiro a mensagem e o ltimo parmetro se o progresso indeterminado (isso s relevante quando cria uma barra de progresso, que discutido na prxima seo). O estilo padro de um dilogo de progresso a roda. Se voc deseja criar uma barra de progresso que mostra o progresso do carregamento com granularidade, mais cdigo necessrio, como ser discutido na prxima seo.

Mostrando uma barra de progresso

Para mostrar a progresso com uma barra de progresso animada: 1. Inicialize o ProgressDialog com o construtor da classe,

ProgressDialog(Context). 2. Defina o estilo de progressos para "STYLE_HORIZONTAL" com

setProgressStyle(int) e defina as outras propriedades, como a mensagem. 3. Quando estiver pronto para mostrar o dilogo, chame show() ou devolva o ProgressDialog do onCreateDialog(int) de retorno. 4. Voc pode incrementar a quantidade de progresso exibida na barra chamando tanto setProgress(int) com um valor para a porcentagem total concluda ou incrementProgressBy(int) com um valor incremental para adicionar porcentagem total concluda at agora. Por exemplo, sua configurao pode se parecer como esta:
ProgressDialog progressDialog; progressDialog = new ProgressDialog(mContext); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMessage("Loading..."); progressDialog.setCancelable(false);

ANDROID, uma viso geral Anderson Duarte de Amorim

163

A configurao simples. A maior parte do cdigo necessrio para criar um dilogo de progresso est realmente envolvida no processo que atualiz-lo. Voc pode achar que necessrio criar um segundo thread em sua aplicao para este trabalho e, em seguida, relatar o progresso de volta atividade do thread de interface do usurio com um Handler do objeto. Se voc no est familiarizado com o uso de threads adicionais com um manipulador, vejo o exemplo abaixo, que utiliza um segundo thread para incrementar um dilogo de progresso gerido pela atividade. Exemplo ProgressDialog com um segundo thread Este exemplo usa um segundo thread para acompanhar o andamento de um processo (que na verdade s conta at 100). O thread envia uma Message de volta atividade principal atravs de um Handler a cada hora em que algum progresso feito. A atividade principal, em seguida, atualiza o ProgressDialog.
package com.example.progressdialog; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class NotificationTest extends Activity { static final int PROGRESS_DIALOG = 0; Button button; ProgressThread progressThread; ProgressDialog progressDialog; /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Setup the button that starts the progress dialog button = (Button) findViewById(R.id.progressDialog); button.setOnClickListener(new OnClickListener(){ public void onClick(View v) { showDialog(PROGRESS_DIALOG); } }); } protected Dialog onCreateDialog(int id) {

ANDROID, uma viso geral Anderson Duarte de Amorim

164

switch(id) { case PROGRESS_DIALOG: progressDialog = new ProgressDialog(NotificationTest.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMessage("Loading..."); return progressDialog; default: return null; } } @Override protected void onPrepareDialog(int id, Dialog dialog) { switch(id) { case PROGRESS_DIALOG: progressDialog.setProgress(0); progressThread = new ProgressThread(handler); progressThread.start(); } // Define the Handler that receives messages from the thread and update the progress final Handler handler = new Handler() { public void handleMessage(Message msg) { int total = msg.arg1; progressDialog.setProgress(total); if (total >= 100){ dismissDialog(PROGRESS_DIALOG); progressThread.setState(ProgressThread.STATE_DONE); } } }; /** Nested class that performs progress calculations (counting) */ private class ProgressThread extends Thread { Handler mHandler; final static int STATE_DONE = 0; final static int STATE_RUNNING = 1; int mState; int total; ProgressThread(Handler h) { mHandler = h; } public void run() { mState = STATE_RUNNING; total = 0; while (mState == STATE_RUNNING) { try { Thread.sleep(100); } catch (InterruptedException e) { Log.e("ERROR", "Thread Interrupted"); } Message msg = mHandler.obtainMessage(); msg.arg1 = total;

ANDROID, uma viso geral Anderson Duarte de Amorim

165

mHandler.sendMessage(msg); total++; } } /* sets the current state for the thread, * used to stop the thread */ public void setState(int state) { mState = state; } } }

Criando uma caixa de dilogo personalizada


Se voc quiser um projeto personalizado para um dilogo, voc pode criar seu prprio layout para a janela de dilogo com elementos de layout e de widget. Depois de definido o layout, passar o objeto View raiz ou identificao do recurso de layout para setContentView(View). Por exemplo, para criar o dilogo mostrado acima: 1. Criar um layout XML salvo como custom_dialog.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_root" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" > <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginRight="10dp" /> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="fill_parent" android:textColor="#FFF" /> </LinearLayout>

Esta XML define um ImageView e um TextView dentro de um LinearLayout. 2. Definir o layout acima como o contedo da View da caixa de dilogo e definir o contedo dos elementos ImageView e TextView:

ANDROID, uma viso geral Anderson Duarte de Amorim

166

Context mContext = getApplicationContext(); Dialog dialog = new Dialog(mContext); dialog.setContentView(R.layout.custom_dialog); dialog.setTitle("Custom Dialog"); TextView text = (TextView) dialog.findViewById(R.id.text); text.setText("Hello, this is a custom dialog!"); ImageView image = (ImageView) dialog.findViewById(R.id.image); image.setImageResource(R.drawable.android);

Depois de instanciar o dilogo, definir o layout personalizado de contedo como contedo da View da caixa de dilogo com setContentView(int), passando o ID do recurso de layout. Agora que o dilogo tem um layout definido, voc pode capturar objetos View do layout com findViewById(int) e modificar seu contedo. 3. isso a. Agora voc pode mostrar o dilogo como descrito em Mostrando um Dilogo. Um dilogo feito com a classe de dilogo base deve ter um ttulo. Se voc no chamar setTitle(), o espao usado para o ttulo continua vazio, mas ainda visvel. Se voc no quer um ttulo a todos, ento voc deve criar o seu dilogo personalizado usando a classe AlertDialog. No entanto, porque um AlertDialog mais fcilmente criado com o AlertDialog.Builder, voc no tem acesso ao mtodo setContentView(int) utilizado acima. Em vez disso, voc deve usar setView(View). Este mtodo aceita um objeto View, por isso necessrio inflar o layout do objeto View da raiz do XML. Para inflar o layout XML, recuperar o LayoutInflater com getLayoutInflater() (ou getSystemService()), e depois chamar inflate(int, ViewGroup), onde o primeiro parmetro o ID do recurso layout e o segundo a identificao da View raiz. Neste ponto, voc pode usar o layout inflado para encontrar objetos View no layout e definir o contedo dos elementos ImageView e TextView. Ento instanciar o

AlertDialog.Builder e definir o layout inflados para o dilogo com setView(View). Aqui est um exemplo, criando um layout personalizado em um AlertDialog:
AlertDialog.Builder builder; AlertDialog alertDialog; Context mContext = getApplicationContext(); LayoutInflater inflater = (LayoutInflater)

ANDROID, uma viso geral Anderson Duarte de Amorim

167

mContext.getSystemService(LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.custom_dialog, (ViewGroup) findViewById(R.id.layout_root)); TextView text = (TextView) layout.findViewById(R.id.text); text.setText("Hello, this is a custom dialog!"); ImageView image = (ImageView) layout.findViewById(R.id.image); image.setImageResource(R.drawable.android); builder = new AlertDialog.Builder(mContext); builder.setView(layout); alertDialog = builder.create();

Usando um AlertDialog para o seu layout personalizado permite-lhe tirar partido das funcionalidades incorporadas AlertDialog como botes geridos, listas selecionveis, um ttulo, um cone e assim por diante.

ANDROID, uma viso geral Anderson Duarte de Amorim

168

Manipulando eventos de UI
No Android, h mais de um caminho para interceptar os eventos de interao do usurio com seu aplicativo. Ao considerar os eventos dentro de sua interface de usurio, a abordagem consiste em capturar os eventos do objeto View especfico com que o usurio interage. A classe View fornece os meios para faz-lo. Entre as diversas classes View que voc usar para compor seu layout, voc pode observar vrios mtodos de retorno pblicos que paream teis para eventos de UI. Esses mtodos so chamados pelo framework Android, quando a respectiva ao ocorre no objeto. Por exemplo, quando uma exibio (como um boto) tocada, o mtodo onTouchEvent() chamado no objeto. No entanto, a fim de interceptar isso, voc deve estender a classe e substituir o mtodo. No entanto, estender cada objeto View, a fim de lidar com um evento como esse no seria prtico. por isso que a classe View tambm contm uma coleo de interfaces aninhadas com callbacks que podem ser muito mais fcil de definir. Essas interfaces, chamadas de event listeners, so o seu bilhete para capturar a interao do usurio com sua interface do usurio. Enquanto voc vai utilizar mais comumente os ouvintes de evento para receber a interao do usurio, pode chegar um momento em que voc quer estender uma classe, no intuito de construir um componente personalizado. Talvez voc queira estender a classe Button para fazer algo mais extravagante. Neste caso, voc ser capaz de definir o comportamento de eventos padro para sua classe usando a classe de manipuladores de eventos.

Os ouvintes de eventos
Um receptor de evento uma interface na classe View que contm um mtodo de retorno nico. Esses mtodos sero chamados pelo framework Android quando o View para o receptor tenha sido registado desencadeada pela interao do usurio com o item na interface do usurio.

ANDROID, uma viso geral Anderson Duarte de Amorim

169

Includo nas interfaces de ouvinte de evento so os mtodos de retorno seguintes: onClick() A partir do View.OnClickListener. chamado quando o usurio toca o item (quando em modo de tocar), ou incide sobre o item com a navegao por teclas ou trackball e pressiona a tecla "enter" ou pressiona o trackball. onLongClick() De View.OnLongClickListener. Isto chamado quando o usurio toca e prende o item (quando no modo de tocar), ou incide sobre o item com a navegao por teclas ou trackball e pressiona e mantm a tecla "enter" ou pressiona e mantm pressionada a trackball (por um segundo). onFocusChange() De View.OnFocusChangeListener. Isto chamado quando o usurio navega para ou longe do ponto, utilizando atalhos ou trackball. onKey() De View.OnKeyListener. Isto chamado quando o usurio est centrado sobre o item e pressiona ou solta uma tecla no dispositivo. onTouch() De View.OnTouchListener. Isto chamado quando o usurio executa uma ao qualificada como um evento de toque, incluindo pressionar, soltar, ou qualquer movimento na tela (dentro dos limites do item). onCreateContextMenu() De View.OnCreateContextMenuListener. Isto chamado quando um menu de contexto est sendo construdo (como o resultado de um "clique longo" sustentado). Esses mtodos so os nicos habitantes da suas respectivas interfaces. Para definir um desses mtodos e lidar com seus eventos, implemente a interface aninhada em sua

ANDROID, uma viso geral Anderson Duarte de Amorim

170

atividade ou defina-a como uma classe annima. Em seguida, passe uma instncia da sua aplicao com os respectivos mtodos View.set...Listener(). (Por exemplo, chamar setOnClickListener() e pass-la a implementao do OnClickListener). O exemplo abaixo mostra como registrar um receptor no clique de um boto.
// Create an anonymous implementation of OnClickListener private OnClickListener mCorkyListener = new OnClickListener() { public void onClick(View v) { // do something when the button is clicked } }; protected void onCreate(Bundle savedValues) { ... // Capture our button from layout Button button = (Button)findViewById(R.id.corky); // Register the onClick listener with the implementation above button.setOnClickListener(mCorkyListener); ... }

Voc tambm pode achar mais conveniente para implementar OnClickListener como parte de sua atividade. Isso ir evitar a carga horria extra e alocao de objetos. Por exemplo:
public class ExampleActivity extends Activity implements OnClickListener { protected void onCreate(Bundle savedValues) { ... Button button = (Button)findViewById(R.id.corky); button.setOnClickListener(this); } // Implement the OnClickListener callback public void onClick(View v) { // do something when the button is clicked } ... }

Observe que a chamada de onClick()no exemplo acima no tem valor de retorno, mas alguns mtodos ouvintes devem retornar um boolean. A razo depende do evento. Para os poucos que o fazem, aqui est o porqu: onLongClick() - Retorna um booleano para indicar se voc tem consumido o evento e que no deve ser levado adiante. Ou seja, retornar true para indicar que voc tem tratado o evento e deve parar por aqui; retornar false se voc no tem

ANDROID, uma viso geral Anderson Duarte de Amorim

171

lidado com isso e/ou o evento deve continuar para qualquer outro receptor onclick. onKey() - Retorna um booleano para indicar se voc tem consumido o evento e que no deve ser levada adiante. Ou seja, retornar true para indicar que voc tem tratado o evento e deve parar por aqui; retornar false se voc no tem lidado com isso e/ou o evento deve continuar a todo ouvinte on-key. onTouch() - Retorna um booleano para indicar se o ouvinte consome este evento. O importante que este evento pode ter vrias aes que se sucedem. Ento, se voc retornar falso quando o evento de ao abaixo recebido, voc indica que no consumiram o evento e tambm no esto interessados em aes subseqentes deste evento. Assim, voc no ser chamado para outras aes dentro do evento, como um gesto do dedo, ou um eventual evento de ao acima. Lembre-se que os principais eventos so sempre entregues para a corrente View em foco. Eles so enviados a partir do topo da hierarquia de View e, em seguida, para baixo, at chegar ao destino apropriado. Se a sua view (ou filho de sua view) atualmente tem o foco, ento voc pode ver o curso de eventos atravs do mtodo dispatchKeyEvent(). Como alternativa captura de eventos-chave atravs da sua view, voc tambm pode receber todos os eventos dentro de sua atividade com onKeyDown() e onKeyUp(). Nota: O Android vai chamar os manipuladores de eventos e depois os manipuladores padro apropriados a partir da definio de segunda classe. Como tal, retornando true destes ouvintes de evento ir parar a propagao do evento para ouvintes de eventos e tambm ir bloquear o retorno de chamada para o manipulador de eventos padro no View. Ento, tenha a certeza de que deseja encerrar o caso quando voc retornar true.

Manipuladores de eventos
Se voc est construindo um componente personalizado de view, ento voc vai ser capaz de definir vrios mtodos de retorno usados como manipuladores de eventos padro. No documento Construindo Componentes Personalizados, voc aprender a ver alguns dos retornos comuns usados para tratamento de eventos, incluindo:

ANDROID, uma viso geral Anderson Duarte de Amorim

172

onKeyDown(int, KeyEvent) - Chamado quando um evento de nova tecla ocorre. onKeyUp(int, KeyEvent) - Chamado quando um evento de tecla para cima ocorre. onTrackballEvent(MotionEvent) - Chamado quando um evento de movimento de trackball ocorre. onTouchEvent(MotionEvent) - Chamado quando um evento do movimento da tela de toque ocorre. onFocusChanged(boolean, int, Rect) - Chamado quando a view ganha ou perde o foco. Existem alguns outros mtodos que voc deve estar ciente de que no so parte da classe View, mas podem impactar diretamente a forma como voc capaz de manipular eventos. Portanto, ao gerenciar eventos mais complexos dentro de um layout, considere estes outros mtodos: Activity.dispatchTouchEvent(MotionEvent) - Isso permite que sua atividade possa interceptar todos os eventos de toque antes de serem enviados para a janela. ViewGroup.onInterceptTouchEvent(MotionEvent) - Isso permite que um ViewGroup possa assistir a eventos como eles so distribudos aos views filhos. ViewParent.requestDisallowInterceptTouchEvent(boolean) - Chamar esta em cima de um pai view para indicar que ela no deve interceptar eventos de contato com onInterceptTouchEvent(MotionEvent) .

Modo de toque
Quando um usurio est navegando uma interface de usurio com as teclas direcionais ou um trackball, necessrio dar ateno aos itens de recurso (como botes) que o usurio possa ver o que vai aceitar a entrada. Se o dispositivo tem capacidades de toque, no entanto, o usurio comea a interagir com a interface ao toc-lo, ento ele no mais

ANDROID, uma viso geral Anderson Duarte de Amorim

173

necessrio para destacar itens, ou dar enfoque a uma viso particular. Assim, existe um modo de interao com o nome "modo de toque." Para um dispositivo sensvel ao toque, uma vez que o usurio toca a tela, o aparelho entra em modo de tocar. Deste ponto em diante, somente as views em que o isFocusableInTouchMode() est true podero ser focadas, como os widgets de edio de texto. Outros views que so palpveis, como botes, no vo tirar o foco quando tocado; eles vo simplesmente focar seus ouvintes com um clique, quando pressionados. Toda vez que um usurio pressiona uma tecla direcional ou rola com uma trackball, o aparelho sair do modo de tocar, e encontrar um visual de tirar o foco. Agora, o usurio pode continuar interagindo com a interface do usurio sem tocar na tela. O estado modo de tocar mantido ao longo de todo o sistema (todas as janelas e atividades). Para consultar o estado atual, voc pode chamar isInTouchMode() para ver se o dispositivo est no modo de tocar.

Manipulao do foco
O framework vai lidar com as rotinas de movimento do foco em resposta entrada do usurio. Isso inclui a mudana do foco nas views que so removidas ou escondidas, ou quando as views novos se tornam disponveis. Views indicam a sua disponibilidade para tirar o foco atravs do mtodo isFocusable(). Para definir se uma View pode tirar o foco, chame setFocusable(). Quando em modo de tocar, voc pode consultar se uma View permite focar com isFocusableInTouchMode(). Voc pode mudar isso com setFocusableInTouchMode(). Movimento do foco baseado em um algoritmo que encontra o vizinho mais prximo em uma determinada direo. Em casos raros, o algoritmo padro pode no coincidir com o comportamento desejado para o desenvolvedor. Nessas situaes, voc pode fornecer substituies explcitas com os atributos XML a seguir no arquivo de layout: nextFocusDown, nextFocusLeft, nextFocusRight, e nextFocusUp. Adicione um desses atributos para o View a partir do qual o foco est saindo. Defina o valor do atributo a ser o ID do view para quem o foco deve ser dado. Por exemplo:

ANDROID, uma viso geral Anderson Duarte de Amorim

174

<LinearLayout android:orientation="vertical" ... > <Button android:id="@+id/top" android:nextFocusUp="@+id/bottom" ... /> <Button android:id="@+id/bottom" android:nextFocusDown="@+id/top" ... /> </LinearLayout>

Normalmente, neste layout vertical, navegando a partir do primeiro boto no leva a lugar nenhum, nem iria navegar abaixo do segundo boto. Agora que o boto superior foi definido como um fundo com o nextFocusUp (e vice-versa), o foco de navegao ir circular de cima para baixo e de baixo para cima. Se voc gostaria de declarar o view como passvel de foco em sua interface do usurio (quando no tradicional), adicione o atributo XML android:focusable para a view, na sua declarao de layout. Defina o valor true. Voc pode tambm declarar uma view como passvel de foco enquanto em modo de toque com

android:focusableInTouchMode. Para solicitar uma exibio especial para ter foco, chame requestFocus(). Para ouvir os eventos de foco (ser notificado quando um view recebe ou perde foco), use onFocusChange().

ANDROID, uma viso geral Anderson Duarte de Amorim

175

Notificar o usurio
Vrios tipos de situaes podem surgir que requerem a notificao do usurio sobre um evento que ocorre em sua aplicao. Alguns eventos requerem que o usurio responda e outros no. Por exemplo: Quando um evento como salvar um arquivo for concluda, uma pequena mensagem deve aparecer para confirmar que o salvamento foi bem sucedido. Se o aplicativo executado em segundo plano e requer ateno do usurio, o aplicativo deve criar uma notificao que permite ao usurio responder a convenincia dele ou dela. Se o aplicativo est executando o trabalho que o usurio deve aguardar (como carregar um arquivo), o aplicativo deve mostrar uma roda de progresso pairando ou uma barra. Cada uma dessas tarefas de notificao podem ser conseguidas usando uma tcnica diferente: Uma notificao brinde, por breves mensagens que vm do fundo. Uma notificao na barra de status, lembretes persistentes que vm do fundo e solicitam resposta do usurio. Uma notificao de dilogo, para as notificaes de atividades relacionadas.

Notificao brinde
Uma notificao brinde uma mensagem que aparece na superfcie da janela. Ela s enche o espao necessrio para a mensagem e a atividade atual do usurio permanece visvel e interativa. A notificao automaticamente desaparece, e no aceita eventos de interao. Como um brinde pode ser criado a partir de um servio em background, aparece mesmo que o aplicativo no esteja visvel.

ANDROID, uma viso geral Anderson Duarte de Amorim

176

Um brinde melhor para mensagens de texto curtas, como "Arquivo salvo", quando voc est bastante certo de que o usurio est prestando a ateno na tela. Um brinde no pode aceitar eventos de interao do usurio, se voc gostaria que o usurio respondesse e agisse, considere usar uma notificao na barra de status.

Criando notificaes brinde


A imagem abaixo mostra uma notificao brinde de exemplo da aplicao do alarme. Uma vez que um alarme ativado, um brinde exibido para garantir que o alarme foi ajustado. Um brinde pode ser criado e exibido a partir de uma Activity ou Service. Se voc criar uma notificao de brinde de um servio, ele aparece na frente da atividade atualmente em foco. Se a resposta do usurio com a notificao exigida, considere usar uma notificao na barra de status. O Bsico Primeiro, instanciar um objeto Toast com um dos mtodos makeText(). Este mtodo usa trs parmetros: a aplicao Context, a mensagem de texto e a durao para o brinde. Ele retorna um objeto Toast inicializado corretamente. Voc pode exibir a notificao brinde com show(), como mostrado no exemplo a seguir:
Context context = getApplicationContext(); CharSequence text = "Hello toast!"; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(context, text, duration); toast.show();

Este exemplo demonstra tudo o que precisa para a maioria das notificaes brinde. Raramente necessrio algo a mais. Voc pode, no entanto, querer a posio do brinde diferente ou at mesmo usar o seu prprio layout, em vez de uma simples mensagem de texto. As sees a seguir descrevem como voc pode fazer essas coisas.

ANDROID, uma viso geral Anderson Duarte de Amorim

177

Posicionar o seu brinde Uma notificao brinde padro aparece perto da parte inferior da tela, centralizado horizontalmente. Voc pode alterar esta posio com o mtodo setGravity(int, int, int). Este aceita trs parmetros: a constante Gravity, um deslocamento da posio x e um deslocamento da posio y. Por exemplo, se voc decidir que o brinde deve aparecer no canto superior esquerdo, voc pode definir a gravidade como este:
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);

Se voc quiser deslocar a posio para a direita, aumente o valor do segundo parmetro. Para empurr-lo para baixo, aumente o valor do ltimo parmetro. Criando uma exibio personalizada brinde Se uma mensagem de texto simples no suficiente, voc pode criar um layout personalizado para a sua notificao brinde. Para criar um layout personalizado, definir um layout de view, em XML ou no cdigo do aplicativo, e passar a View raiz para o mtodo setView(View). Por exemplo, voc pode criar o layout para o brinde visvel na imagem esquerda, com o seguinte XML (salvo como toast_layout.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/toast_layout_root" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" android:background="#DAAA" > <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginRight="10dp" /> <TextView android:id="@+id/text"

ANDROID, uma viso geral Anderson Duarte de Amorim

178

android:layout_width="wrap_content" android:layout_height="fill_parent" android:textColor="#FFF" /> </LinearLayout>

Observe que a identificao do elemento LinearLayout "toast_layout". Voc deve usar essa identificao para inflar o layout do XML, como mostrado aqui:
LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root)); ImageView image = (ImageView) layout.findViewById(R.id.image); image.setImageResource(R.drawable.android); TextView text = (TextView) layout.findViewById(R.id.text); text.setText("Hello! This is a custom toast!"); Toast toast = new Toast(getApplicationContext()); toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0); toast.setDuration(Toast.LENGTH_LONG); toast.setView(layout); toast.show();

Primeiro, recupere o LayoutInflater com getLayoutInflater() (ou getSystemService()), e depois infle o layout de XML usando inflate(int, ViewGroup). O primeiro parmetro o ID do recurso layout e o segundo a View raiz. Voc pode usar esse layout inflado para encontrar mais objetos view no layout, agora capturar e definir o contedo dos elementos ImageView e TextView. Finalmente, crie um novo brinde com Toast(Context) e defina algumas propriedades do brinde, tais como a gravidade e durao. Em seguida, chame setView(View) e passe seu layout inflado. Agora voc pode exibir o brinde com o seu layout personalizado, chamando show(). Nota: No use o construtor pblico para um brinde, a menos que v definir o layout com setView(View). Se voc no tem um layout personalizado para o uso, voc deve usar makeText(Context, int, int) para criar o Toast.

Notificao na barra de status


Uma notificao na barra de status adiciona um cone para barra de status do sistema (com opcionais relgio/mensagem de texto) e uma mensagem expandida na janela

"Notificaes". Quando o usurio seleciona a mensagem

ANDROID, uma viso geral Anderson Duarte de Amorim

179

expandida, o Android aciona uma Intent que definida pela notificao (geralmente para lanar uma Activity). Voc tambm pode configurar a notificao para alertar o usurio com um som, uma vibrao e as luzes piscando no dispositivo. Este tipo de notificao ideal quando o aplicativo est funcionando em um servio de fundo e h necessidade de notificar o usurio sobre um evento. Se voc precisa alertar o usurio sobre um evento que ocorre durante a sua atividade que ainda est em foco, considere usar uma notificao de dilogo em vez disso.

Criao de notificaes da barra de status


Uma notificao na barra de status deve ser usada para qualquer caso em que um servio de background precisa alertar o usurio sobre um evento que exige uma resposta. Um servio de fundo nunca deve iniciar uma atividade por conta prpria a fim de receber a interao do usurio. O servio deveria criar uma notificao na barra de status que vai lanar a atividade quando selecionado pelo usurio. A imagem abaixo mostra a barra de status com um cone de notificao no lado esquerdo.

A imagem seguinte mostra mensagem expandida de notificao na janela "Notificaes". O usurio pode visualizar a janela de notificaes, puxando para baixo a barra de status (ou selecionando Notificaes no menu de opes da Home).

O Bsico Uma Activity ou Service pode iniciar uma notificao na barra de status. Porque uma atividade pode executar aes somente quando ela est ativa e em foco, voc deve criar suas notificaes de um servio. Desta forma, a notificao pode ser criada a partir do ANDROID, uma viso geral Anderson Duarte de Amorim

180

fundo, enquanto o usurio est usando outra aplicao ou quando o dispositivo estiver dormindo. Para criar uma notificao, voc deve usar duas classes: Notification e NotificationManager. Use uma instncia da classe Notification para definir as propriedades de sua notificao na barra de status, como o cone da barra de status, a mensagem expandida e configuraes extras, como um som para tocar. O NotificationManager um servio do sistema Android que executa e gerencia todas as notificaes. Voc no pode instanciar o NotificationManager. A fim de dar-lhe a sua notificao, voc deve recuperar uma referncia para o NotificationManager com getSystemService() e ento, quando voc quer notificar o usurio, pass-lo com seu objeto de notificao notify(). Para criar uma notificao de barra de status: 1. Obtenha uma referncia para o NotificationManager:
String ns NotificationManager getSystemService(ns); = Context.NOTIFICATION_SERVICE; mNotificationManager = (NotificationManager)

2. Instanciar a notificao:
int icon = R.drawable.notification_icon; CharSequence tickerText = "Hello"; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, tickerText, when);

3. Definir mensagem expandida e inteno da notificao:


Context context = getApplicationContext(); CharSequence contentTitle = "My notification"; CharSequence contentText = "Hello World!"; Intent notificationIntent = new Intent(this, MyClass.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

4. Passe a notificao ao NotificationManager:


private static final int HELLO_ID = 1; mNotificationManager.notify(HELLO_ID, notification);

isso a. Seu usurio j foi notificado.

ANDROID, uma viso geral Anderson Duarte de Amorim

181

Gerenciando suas notificaes O NotificationManager um servio do sistema que gerencia todas as notificaes. Voc deve obter uma referncia a ele com o mtodo getSystemService(). Por exemplo:
String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);

Quando voc quiser enviar sua notificao na barra de status, passar o objeto de notificao ao NotificationManager com notify(int, Notification). O primeiro parmetro o ID nico para a notificao e o segundo o objeto de notificao. O ID identifica a notificao a partir da sua aplicao. Isso necessrio se voc precisa atualizar a notificao (se o aplicativo gerencia diferentes tipos de notificaes) ou selecionar a ao apropriada quando o usurio retornar para a sua aplicao atravs da inteno definida na notificao. Para apagar a notificao de barra de status quando o usurio seleciona a partir da janela de notificaes, adicione a flag "FLAG_AUTO_CANCEL" de seu objeto de notificao. Voc tambm pode limpar manualmente com cancel(int), passando-lhe a identificao ou notificao ou limpar todas as suas notificaes com cancelAll(). Criando uma notificao Um objeto Notification define os detalhes da mensagem de notificao que exibida na barra de status e janela de "Notificaes", e qualquer alerta de outras configuraes, tais como sons e luzes piscando. Uma notificao de barra de status exige o seguinte: Um cone da barra de status Uma mensagem expandida e ttulo para o modo expandido (a menos que voc defina uma exibio personalizada ampliada) Um PendingIntent, para ser acionado quando a notificao for selecionada As configuraes opcionais para a notificao de barra de status incluem: Uma mensagem de texto-relgio para a barra de status Um som de alerta ANDROID, uma viso geral Anderson Duarte de Amorim

182

Uma configurao vibrar Uma definio LED piscando O kit de arranque para uma nova notificao inclui o construtor Notification(int, CharSequence, long) e o mtodo setLatestEventInfo(Context, CharSequence,

CharSequence, PendingIntent). Estes definem todas as definies necessrias para uma notificao. O trecho a seguir demonstra a configurao de notificao de base:
int icon = R.drawable.notification_icon; // icon from resources CharSequence tickerText = "Hello"; // ticker-text long when = System.currentTimeMillis(); // notification time Context context = getApplicationContext(); // application Context CharSequence contentTitle = "My notification"; // expanded message title CharSequence contentText = "Hello World!"; // expanded message text Intent notificationIntent = new Intent(this, MyClass.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); // the next two lines initialize the Notification, using the configurations above Notification notification = new Notification(icon, tickerText, when); notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

Atualizando a notificao Voc pode atualizar as informaes em sua notificao de barra de status como eventos que continuam a ocorrer em seu aplicativo. Por exemplo, quando uma nova mensagem de texto SMS chega antes que as mensagens anteriores foram lidas, o aplicativo de mensagens atualiza as notificaes existentes para exibir o nmero total de novas mensagens recebidas. Esta prtica, de uma atualizao de notificao existente muito melhor do que a adio de novas notificaes NotificationManager porque evita a desordem na janela de notificaes. Porque cada notificao unicamente identificada pelo NotificationManager com um nmero de identificao inteiro, voc pode revisar a notificao chamando setLatestEventInfo() com novos valores, mudar alguns valores de campo da notificao, e depois chamar notify() novamente. Voc pode rever cada propriedade com os campos de membro de objeto (exceto para o contexto e no ttulo da mensagem expandida e texto). Voc deve sempre revisar a mensagem de texto quando voc atualizar a notificao chamando setLatestEventInfo() com novos valores para contentTitle e contentText. Em seguida, chamar notify() para

ANDROID, uma viso geral Anderson Duarte de Amorim

183

atualizar a notificao. (Claro, se voc criou uma exibio personalizada expandida, atualizar esses valores de texto e ttulo no ter efeito) Adicionando um som Voc pode alertar o usurio com o som de notificao padro (que definido pelo usurio) ou com um som especificado pelo seu aplicativo. Para utilizar o usurio padro do som, adicione "DEFAULT_SOUND" para o campo de padres:
notification.defaults |= Notification.DEFAULT_SOUND;

Para usar um som diferente com as suas notificaes, passe uma referncia URI para o campo de som. O exemplo a seguir usa um arquivo de udio conhecido gravado no carto SD do dispositivo:
notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");

No prximo exemplo, o arquivo de udio escolhido do MediaStore 's ContentProvider:


notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");

Neste caso, a identificao exata do arquivo de mdia ("6") conhecido e anexado ao contedo Uri. Se voc no souber a identificao exata, voc deve consultar todos os meios disponveis no MediaStore com ContentResolver. Se voc deseja que o som repeta continuamente at que o usurio responda notificao ou a notificao seja cancelada, adicione "FLAG_INSISTENT" para o campo de sinalizadores. Nota: Se o campo padro inclui "DEFAULT_SOUND", ento o som padro substitui qualquer som definido pelo campo de som. Adicionando vibrao Voc pode alertar o usurio com o modelo padro de vibrao ou com um modelo de vibrao definido pelo seu aplicativo. Para usar o modelo padro, adicione "DEFAULT_VIBRATE" para o campo de padres:

ANDROID, uma viso geral Anderson Duarte de Amorim

184

notification.defaults |= Notification.DEFAULT_VIBRATE;

Para definir o seu padro de vibrao prpria, passe uma matriz de valores longos para o campo vibrar:
long[] vibrate notification.vibrate = vibrate; = {0,100,200,300};

O longo array define o padro alternado para o comprimento de vibrao e desligando (em milissegundos). O primeiro valor o tempo de espera (desligado) antes de comear, o segundo valor o comprimento da primeira vibrao, o terceiro o comprimento da prxima, e assim por diante. O padro pode ser to longo quanto queira, mas no pode ser configurado para repetir. Nota: Se o campo padro inclui "DEFAULT_VIBRATE", ento a vibrao padro substitui qualquer vibrao definida pelo campo vibrate. Adicionando luzes a piscar Para alertar o usurio com luzes LED, voc pode implementar o modelo de luz padro (se disponvel), ou definir sua prpria cor e padro para as luzes. Para usar a configurao padro de luz, acrescentar "DEFAULT_LIGHTS" para o campo de padres:
notification.defaults |= Notification.DEFAULT_LIGHTS;

Para definir sua prpria cor e padro, definir um valor para o campo ledARGB (para a cor), o campo ledOffMS (perodo de tempo, em milsimos de segundo, para manter a luz apagada), o ledOnMS (perodo de tempo, em milissegundos, para manter a luz acesa), e tambm adicionar "FLAG_SHOW_LIGHTS" para o campo flags:
notification.ledARGB = notification.ledOnMS = notification.ledOffMS = notification.flags |= Notification.FLAG_SHOW_LIGHTS; 0xff00ff00; 300; 1000;

Neste exemplo, a luz verde pisca vrias vezes a cada 300 milsimos de segundo e desliga por um segundo. Nem todas as cores no espectro so suportadas pelo dispositivo de LEDs, e no todo dispositivo que suporta as mesmas cores, ento o hardware estima para o melhor de sua capacidade. Verde a cor mais comum de notificao.

ANDROID, uma viso geral Anderson Duarte de Amorim

185

Mais recursos Voc pode adicionar vrias caractersticas a mais s suas notificaes usando campos de notificao e flags. Algumas caractersticas teis incluem o seguinte: "FLAG_AUTO_CANCEL" Adicione isto ao campo de sinalizadores para cancelar automaticamente a notificao depois que ela selecionada a partir da janela de notificaes. "FLAG_INSISTENT" Adicione isto ao campo de sinalizadores para repetir o udio at que o usurio responda. "FLAG_ONGOING_EVENT" Adicione isto ao campo de sinalizadores para agrupar notificaes ao abrigo do ttulo "em curso" da janela de notificaes. Isso indica que o aplicativo est em curso - seus processos ainda esto em execuo em segundo plano, mesmo quando o aplicativo no visvel (como a msica ou uma chamada de telefone). "FLAG_NO_CLEAR" Adicione isto ao campo de sinalizadores para indicar que a notificao no deve ser limpa pelo boto "Limpar notificaes". Isso particularmente til se a sua notificao est em curso. nmero Esse valor indica o nmero atual de eventos representados pela notificao. O nmero apropriado sobreposto em cima do cone da barra de status. Se voc pretende usar esse campo, ento voc deve comear com "1" quando a notificao for criado pela primeira vez. (Se voc alterar o valor de zero para qualquer coisa maior durante uma atualizao, o nmero no mostrado.)

ANDROID, uma viso geral Anderson Duarte de Amorim

186

iconLevel Esse valor indica o nvel atual de um LevelListDrawable que usado para o cone de notificao. Voc pode animar o cone na barra de status, alterando esse valor para correlacionar com os drawable definido em um LevelListDrawable. Criar uma exibio personalizada expandida Por padro, o modo expandido utilizado na janela "Notificaes" inclui um ttulo de base e mensagem de texto. Estes so definidos por parmetros contentText e contentTitle do mtodo setLatestEventInfo(). No entanto, voc tambm pode definir um layout personalizado para o modo de exibio expandido usando RemoteViews. A imagem direita mostra um exemplo de uma exibio personalizada alargada, que usa um ImageView e TextView em LinearLayout. Para definir seu prprio layout para a mensagem expandida, instancie um objeto RemoteViews e passe-o para o campo contentView da sua notificao. Passe o PendingIntent ao campo contentIntent. Criar uma exibio personalizada expandido mais bem entendido com um exemplo: 1. Criar o layout XML para a exibio expandida. Por exemplo, crie um arquivo chamado layout custom_notification_layout.xml e construa-o assim:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="3dp" > <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginRight="10dp" /> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="fill_parent" android:textColor="#000" /> </LinearLayout>

ANDROID, uma viso geral Anderson Duarte de Amorim

187

Este esquema utilizado para a visualizao expandida, mas o contedo do ImageView e TextView ainda precisam ser definidos pelo aplicativo. RemoteViews oferece alguns mtodos adequados que lhe permitem definir o contedo... 2. No cdigo do aplicativo, use os mtodos RemoveViews para definir a imagem e texto. Em seguida, passe o objeto RemoteViews ao campo contentView da notificao, conforme mostrado neste exemplo:
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout); contentView.setImageViewResource(R.id.image, R.drawable.notification_image); contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view"); notification.contentView = contentView;

Como mostrado aqui, passe o nome do aplicativo do pacote e a identificao de recursos de layout para o construtor RemoteViews. Em seguida, defina o contedo para o ImageView e TextView, usando o setImageViewResource() e setTextViewText(). Em cada caso, passe o ID de referncia do objeto View conveniente que voc deseja definir, juntamente com o valor para essa viso. Finalmente, o objeto RemoteViews passado para a notificao no mbito contentView. 3. Porque voc no precisa do mtodo setLatestEventInfo() quando usando uma exibio personalizada, voc deve definir as intenes para a notificao com o campo contentIntent, como neste exemplo:
Intent notificationIntent = new Intent(this, MyClass.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.contentIntent = contentIntent;

4. A notificao pode ser enviada, como de costume:


mNotificationManager.notify(CUSTOM_VIEW_ID, notification);

A classe RemoteViews tambm inclui mtodos que voc pode usar para facilmente adicionar um Chronometer ou ProgressBar na view expandida da notificao. Para obter mais informaes sobre como criar layouts personalizados com RemoteViews, consulte o RemoteViews.

ANDROID, uma viso geral Anderson Duarte de Amorim

188

Nota: Ao criar uma view expandida customizada, voc deve tomar cuidado especial para garantir que as funes personalizadas de seu layout haja corretamente no dispositivo em orientaes e resolues diferentes. Enquanto este conselho se aplica a todos os layouts view criados no Android, especialmente importante neste caso porque o seu layout de propriedade real muito restrito. Portanto, no faa o seu layout personalizado demasiado complexo e no se esquea de test-lo em vrias configuraes.

Notificao de dilogo
Um dilogo geralmente uma pequena janela que aparece na frente da atividade atual. A atividade perde o foco e o dilogo aceita a interao do usurio. Os dilogos so normalmente utilizados para notificaes e atividades curtas que se relacionem diretamente com a aplicao em curso. Voc deve usar uma caixa de dilogo quando voc precisa mostrar uma barra de progresso ou uma mensagem curta que requer a confirmao do usurio (como um alerta com "OK" e "Cancelar"). Voc pode usar tambm as janelas como parte integrante na interface do aplicativo e para outros fins alm de notificaes. Para uma discusso completa sobre todos os tipos disponveis de dilogos, incluindo seus usos para as notificaes, consulte Criando caixas de dilogo.

ANDROID, uma viso geral Anderson Duarte de Amorim

189

Aplicando estilos e temas


Um estilo um conjunto de propriedades que especificam o aspecto e formato de um View ou janela. Um estilo pode especificar propriedades como altura, padding, cor de fonte, tamanho de fonte, cor de fundo e muito mais. Um estilo definido em um recurso de XML que separado do XML que especifica o layout. Estilos em Android compartilham uma filosofia semelhante de estilo em cascata em web-design que permitem a voc separar o design do contedo. Por exemplo, usando um estilo, voc pode ter este layout XML:
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#00FF00" android:typeface="monospace" android:text="@string/hello" />

E transformar nisso:
<TextView style="@style/CodeFont" android:text="@string/hello" />

Todos os atributos relacionados com o estilo foram removidos do layout XML e colocado em uma definio de estilo chamado CodeFont, e depois aplicado com o atributo style. Voc ver a definio para esse estilo na seo seguinte. Um tema um estilo aplicado a toda uma Activity ou aplicao, ao invs de um indivduo View (como no exemplo acima). Quando um estilo aplicado como um tema, a cada view da atividade ou da aplicao sero aplicados cada propriedade de estilo que ele suporta. Por exemplo, voc pode aplicar o mesmo estilo CodeFont como um tema para uma atividade e, em seguida, todo o texto dentro dessa atividade dever ter fonte monoespaada verde.

Definio de estilos
Para criar um conjunto de estilos, salve um arquivo XML no diretrio res/values/ do seu projeto. O nome do arquivo XML arbitrrio, mas deve usar a extenso .xml e ser salvo na pasta res/values/. O n raiz do arquivo XML deve ser <resources>. Para cada estilo que voc quer criar, adicione um elemento <style> para o arquivo com um nome que identifica o estilo (este atributo obrigatrio). Em seguida, adicione um elemento <item> para cada propriedade desse estilo, com um nome que declara a ANDROID, uma viso geral Anderson Duarte de Amorim

190

propriedade de estilo e um valor para ir com ele (este atributo obrigatrio). O valor para o <item> pode ser uma seqncia de palavras-chave, uma cor hexadecimal, uma referncia a outro tipo de recurso, ou outro valor, dependendo da propriedade de estilo. Aqui est um exemplo de arquivo com um estilo nico:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="CodeFont" parent="@android:style/TextAppearance.Medium"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:textColor">#00FF00</item> <item name="android:typeface">monospace</item> </style> </resources>

Cada filho do elemento <resources> convertido em um objeto de recurso do aplicativo em tempo de compilao, que pode ser referenciado pelo valor do atributo name do elemento <style>. Este estilo de exemplo pode ser referenciado a partir de um layout XML como @style/CodeFont (como demonstrado na introduo acima). O atributo parent no elemento <style> opcional e especifica o ID do recurso de um outro estilo a partir do qual este estilo deve herdar propriedades. Voc pode, ento, substituir as propriedades de estilo herdado se voc quiser. Lembre-se, um estilo que voc deseja usar como uma atividade ou tema de aplicao definido em XML exatamente do mesmo jeito que um estilo para uma view. Um estilo, como o definido acima pode ser aplicado como um estilo para uma nica view ou como um tema para uma atividade ou aplicao inteira. Como aplicar um estilo para uma viso nica ou como um tema de aplicao discutido mais tarde.

Herana
O atributo parent no elemento <style> permite que voc especifique um estilo a partir do qual o seu estilo deve herdar propriedades. Voc pode usar isso para herdar propriedades de um estilo existente e, em seguida, definir apenas as propriedades que deseja alterar ou acrescentar. Voc pode herdar de estilos que voc criou para si mesmo ou de diferentes estilos que esto construdos na plataforma (Veja Usando estilos e temas da plataforma abaixo, para obter informaes sobre herana de estilos definidos pela plataforma Android). Por exemplo, voc pode herdar a aparncia do texto padro da plataforma Android e, em seguida, modific-lo:

ANDROID, uma viso geral Anderson Duarte de Amorim

191

<style name="GreenText" parent="@android:style/TextAppearance"> <item name="android:textColor">#00FF00</item> </style>

Se voc quer herdar os estilos que voc definiu para si mesmo, voc no tem que usar o atributo parent. Em vez disso, apenas preceda o nome do estilo que voc quer herdar ao nome do seu novo estilo, separados por um perodo. Por exemplo, para criar um novo estilo que herda o estilo CodeFont definido anteriormente, mas fazer a cor vermelha, voc pode criar o novo estilo como este:
<style name="CodeFont.Red"> <item name="android:textColor">#FF0000</item> </style>

Observe que no h atributo parent na tag <style>, mas porque o atributo name comea com a CodeFont nome do estilo (que um estilo que voc criou), este estilo herda todas as propriedades de estilo a partir desse estilo. Este estilo, em seguida, substitui a propriedade android:textColor para tornar o texto vermelho. Voc pode fazer referncia a este novo estilo como @style/CodeFont.Red. Voc pode continuar herdando assim tantas vezes quanto quiser, encadeando os nomes com os perodos. Por exemplo, voc pode estender CodeFont.Red ser maior, com:
<style name="CodeFont.Red.Big"> <item name="android:textSize">30sp</item> </style>

Este herda de ambos os estilos CodeFont e CodeFont.Red, em seguida, adiciona a propriedade android:textSize. Nota: Essa tcnica de herana por encadeando de nomes s funciona para estilos definidos por seus prprios recursos. Voc no pode herdar estilos internos do Android desta forma. Para fazer referncia a um estilo incorporado, como TextAppearance, voc deve usar o atributo parent.

Propriedades do estilo
Agora que voc entende como um estilo definido, preciso saber que tipo de propriedades de estilo definidas pelo <item> esto disponveis. Voc provavelmente est familiarizado com alguns j, como layout_width e textColor. Claro, h muito mais propriedades de estilo que voc pode usar.

ANDROID, uma viso geral Anderson Duarte de Amorim

192

O melhor lugar para encontrar propriedades que se aplicam a um determinado View a referncia de classe correspondente, que lista todos os atributos XML que so suportados. Por exemplo, todos os atributos listados na tabela de atributos XML TextView podem ser usados em uma definio de estilo para um elemento TextView (ou uma de suas subclasses). Um dos atributos listados na referncia android:inputType, ento onde voc normalmente poderia colocar o atributo android:inputType em um elemento <EditText>, assim:
<EditText android:inputType="number" ... />

Voc pode em vez disso criar um estilo para o elemento EditText que inclua esta propriedade:
<style name="Numbers"> <item name="android:inputType">number</item> ... </style>

Portanto, o seu XML para o esquema pode agora aplicar este estilo:
<EditText style="@style/Numbers" ... />

Este exemplo simples pode parecer dar mais trabalho, mas quando voc adiciona mais propriedades de estilo e fatores na possibilidade de voltar a usar o estilo em vrios lugares, o custo-beneficio pode ser enorme. Para uma referncia de todas as propriedades de estilo disponveis, consulte a referncia R.attr. Tenha em mente que todos os objetos view no aceitam todos os atributos de mesmo estilo, ento voc deve, normalmente, referenciar ao especfico View para as propriedades de estilo suportadas. Entretanto, se voc aplicar um estilo a uma exibio que no suporta todas as propriedades de estilo, o view ir aplicar apenas as propriedades que so suportadas e simplesmente ignorar os outros. Algumas propriedades de estilo, no entanto, no so suportadas por qualquer elemento View e s pode ser aplicado como um tema. Estas propriedades de estilo se aplicam a toda a janela e no a qualquer tipo de view. Por exemplo, propriedades de estilo para um tema podem ocultar o ttulo do aplicativo, ocultar a barra de status, ou mudar o fundo da

ANDROID, uma viso geral Anderson Duarte de Amorim

193

janela. Estes tipos de propriedades de estilo no pertencem a nenhum objeto View. Para descobrir essas propriedades de estilo theme-only, veja o R.attr de referncia para os atributos que comeam com window. Por exemplo, windowNoTitle e

windowBackground so propriedades de estilo que s so eficazes quando o estilo aplicado como um tema para uma atividade ou aplicao. Consulte a prxima seo para informaes sobre como aplicar um estilo como um tema. Nota: No se esquea de prefixo dos nomes das propriedades em cada elemento <item> com o android: namespace. Por exemplo: <item name="android:inputType">.

Aplicando estilos e temas para a interface do usurio


H duas maneiras de definir um estilo: Para uma view individual, adicione o atributo style a um elemento view no XML para seu layout. Ou, para uma atividade inteira ou uma aplicao, adicione o atributo android:theme ao elemento <activity> ou <application> no manifesto do Android. Quando voc aplica um estilo a uma nica View no layout, as propriedades definidas pelo estilo so aplicadas somente ao View. Se um estilo aplicado a um ViewGroup, a criana do elemento View no herdar as propriedades de estilo - apenas o elemento ao qual se aplicam diretamente o estilo vai aplicar suas propriedades. No entanto, voc pode aplicar um estilo para que se aplique a todos os elementos View, aplicando o estilo como um tema. Para aplicar uma definio de estilo como um tema, voc deve aplicar o estilo para uma Activity ou aplicao no manifesto do Android. Quando voc fizer isso, todos os View dentro da atividade ou da aplicao sero aplicveis a cada propriedade que ele suporta. Por exemplo, se voc aplicar o estilo CodeFont dos exemplos anteriores a uma atividade, ento todos os elementos View que suportam as propriedades de estilo de texto ir aplic-los. Qualquer viso que no suporta as propriedades vai ignor-los. Se o view suporta apenas algumas das propriedades, ento s aplicar essas propriedades.

Aplicar um estilo a uma view


Veja como definir um estilo para uma exibio no esquema XML: ANDROID, uma viso geral Anderson Duarte de Amorim

194

<TextView style="@style/CodeFont" android:text="@string/hello" />

Agora este TextView ser denominado como definido pelo estilo chamado CodeFont. (Veja o exemplo acima, em Definio de estilos). Nota: O atributo style no usa o android: namespace prefix.

Aplicar um tema a uma atividade ou aplicao


Para definir um tema para todas as atividades de sua aplicao, abra o arquivo AndroidManifest.xml e edite o tag <application> para incluir o atributo android:theme com o nome do estilo. Por exemplo:
<application android:theme="@style/CustomTheme">

Se voc quer um tema aplicado a apenas uma atividade em seu aplicativo, ento, adicione o atributo android:theme ao tag <activity> um de cada vez. Assim como o Android oferece outros recursos internos, h muitos temas pr-definidos que podem ser usados, para evitar escrev-los sozinho. Por exemplo, voc pode usar o tema Dialog e fazer a sua actividade parecer como uma caixa de dilogo:
<activity android:theme="@android:style/Theme.Dialog">

Ou se voc quiser que o fundo seja transparente, usar o tema translcido:


<activity android:theme="@android:style/Theme.Translucent">

Se voc gosta de um tema, mas quer ajust-lo, basta adicionar o tema como o parent do seu tema personalizado. Por exemplo, voc pode modificar o tradicional light theme para usar a sua prpria cor, como esta:
<color name="custom_theme_color">#b0b0ff</color> <style name="CustomTheme" parent="android:Theme.Light"> <item name="android:windowBackground">@color/custom_theme_color</item> <item name="android:colorBackground">@color/custom_theme_color</item> </style>

(Note que a cor precisa ser fornecida como um recurso separado aqui, porque o atributo android:windowBackground suporta apenas uma referncia a outro recurso, ao contrrio do android:colorBackground, a ele pode no ser dada uma cor literal.) Agora use CustomTheme em vez de Theme.Light dentro do Manifesto Android: ANDROID, uma viso geral Anderson Duarte de Amorim
195

<activity android:theme="@style/CustomTheme">

Selecione um tema baseado na verso de plataforma


Novas verses do Android tm temas adicionais disponveis para os aplicativos, e voc pode querer usar estes durante a execuo nessas plataformas, enquanto continuam sendo compatveis com verses anteriores. Voc pode fazer isso atravs de um tema personalizado que usa a seleo de recursos para alternar entre os temas pai diferentes, baseado na verso da plataforma. Por exemplo, aqui est a declarao de um tema personalizado que simplesmente o modelo padro das plataformas do tema light. Ele vai em um arquivo XML por res/values (tipicamente res/values/styles.xml ):
<style name="LightThemeSelector" parent="android:Theme.Light"> ... </style>

Para este tema usar o novo tema hologrfico quando o aplicativo est rodando o Android 3.0 (API Nvel 11) ou superior, voc pode colocar uma declarao alternativa para o tema em um arquivo XML em res/values-v11, mas fazer do tema me o tema hologrfico:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light"> ... </style>

Agora, usar este tema como se fosse qualquer outro, e seu aplicativo passar automaticamente para o tema hologrfico se em execuo no Android 3.0 ou superior. Uma lista de atributos padro que voc pode usar em temas podem ser encontrados em R.styleable.Theme. Para obter mais informaes sobre o fornecimento de recursos alternativos, como os temas e layouts, com base na verso de plataforma ou configuraes de outro dispositivo, consulte o documento Fornecimento de Recursos.

Usando estilos e temas da plataforma


A plataforma Android oferece uma grande coleo de estilos e temas que voc pode usar em seus aplicativos. Voc pode encontrar uma referncia de todos os estilos disponveis na classe R.style. Para usar os estilos listados aqui, substituir todos os ANDROID, uma viso geral Anderson Duarte de Amorim

196

sublinhados no nome do estilo, com um perodo. Por exemplo, voc pode aplicar o Theme_NoTitleBar tema com "@android:style/Theme.NoTitleBar". O R.style, entretanto, no bem documentado e no descreve minuciosamente os estilos, assim, ver o cdigo fonte para estes estilos e temas lhe dar uma compreenso melhor do que as propriedades de estilo de cada um oferece. Para uma melhor referncia para estilos e temas do Android, consulte os seguintes cdigos fonte: Android Styles (styles.xml) Android Temas (themes.xml) Esses arquivos vo te ajudar a aprender atravs do exemplo. Por exemplo, no cdigo fonte de temas Android, voc encontrar uma declarao de <style

name="Theme.Dialog">. Nesta definio, voc ver todas as propriedades que so usadas para estilo de dilogos que so usadas pelo framework Android. Para uma referncia de atributos de estilo disponveis que voc pode usar para definir um estilo ou tema (por exemplo, "windowBackground" ou "textAppearance"), ver R.attr ou a classe View para o qual voc est criando um estilo.

ANDROID, uma viso geral Anderson Duarte de Amorim

197

Recursos de aplicao
Voc deve sempre externar recursos como imagens e seqncias de seu cdigo de aplicao, para que voc possa mant-las de forma independente. Externalizar seus recursos tambm permite que voc fornea recursos alternativos que oferecem suporte a configuraes de dispositivos especficos, como lnguas ou tamanhos de tela diferentes, o que se torna cada vez mais importante quanto mais dispositivos com Android tornamse disponveis com configuraes diferentes. A fim de proporcionar compatibilidade com diferentes configuraes, voc deve organizar os recursos em seu diretrio do projeto res/, usando vrios sub-diretrios que agrupam os recursos por tipo e configurao.

Figura 1. Dois dispositivos diferentes, ambos os usando recursos padro.

Figura 2. Dois dispositivos diferentes, uma usando recursos alternativos.

Para qualquer tipo de recurso, voc pode especificar padro e vrios recursos alternativos para a sua aplicao: Os recursos padro so aqueles que devem ser utilizados independentemente da configurao do aparelho ou quando no existem recursos alternativos que correspondam configurao atual. Recursos alternativos so aqueles que voc j projetou para uso com uma configurao especfica. Para especificar que um grupo de recursos so de uma configurao especfica, acrescente um qualificador de configurao adequada ao nome do diretrio. ANDROID, uma viso geral Anderson Duarte de Amorim

198

Por exemplo, enquanto o seu layout padro de interface do usurio salvo no diretrio res/layout/, voc pode especificar um layout de interface diferente para ser usado quando a tela est na orientao paisagem, salvando-o no diretrio res/layout-land/. Android aplica automaticamente os recursos apropriados por correspondncia configurao atual do dispositivo para os nomes do diretrio de recursos. A figura 1 demonstra como um conjunto de recursos padro de um aplicativo so aplicados a dois dispositivos diferentes, quando no h recursos alternativos disponveis. A Figura 2 mostra o mesmo aplicativo com um conjunto de recursos alternativos que se qualificam para uma das configuraes do dispositivo, assim, os dois dispositivos usam recursos diferentes. A informao acima apenas uma introduo sobre como trabalhar os recursos do aplicativo no Android. Os documentos a seguir fornecem um guia completo de como voc pode organizar seus recursos de aplicao, especificar os recursos alternativos, acess-los em seu aplicativo, e mais: Fornecendo recursos Que tipos de recursos voc pode oferecer em seu aplicativo, onde guard-los, e como criar recursos alternativos para configuraes de dispositivo especfico. Acessando recursos Como utilizar os recursos que voc forneceu, seja por referenci-los a partir do seu cdigo de aplicativo ou de outros recursos XML. Tratando alteraes em runtime Como gerenciar as alteraes de configurao que ocorrem quando sua atividade est em execuo. Localizao Um guia de baixo para cima para localizar seu aplicativo usando recursos alternativos. Enquanto este apenas um uso especfico de recursos alternativos, muito importante para alcanar mais usurios.

ANDROID, uma viso geral Anderson Duarte de Amorim

199

Tipos de recursos Uma referncia de vrios tipos de recursos que voc pode fornecer, descrevendo seus elementos XML, atributos e sintaxe. Por exemplo, esta referncia mostra como criar um recurso para os menus do aplicativo, os desenhos, animaes e muito mais.

ANDROID, uma viso geral Anderson Duarte de Amorim

200

Armazenamento de dados
Android oferece vrias opes para voc guardar dados da aplicao persistente. A soluo que voc escolher depende de suas necessidades especficas, tais como se os dados devem ser privados da sua aplicao ou acessveis para outras aplicaes (e do usurio) e quanto espao seus dados requerem. Suas opes de armazenamento de dados so os seguintes: Preferncias compartilhadas Armazenar dados privados primitivos em pares chave-valor. Armazenamento interno Armazenar dados privados sobre a memria do dispositivo. Armazenamento externo Armazenar dados pblicos sobre o armazenamento compartilhado externo. Bancos de dados SQLite Armazenar dados estruturados em um banco privado. Conexo de rede Armazenar dados na web com seu servidor de rede prpria. Android fornece uma maneira para que voc exponha seus dados pessoais, mesmo para outras aplicaes - com um provedor de contedo. Um provedor de contedo um componente opcional que expe acesso de leitura/gravao sua aplicao de dados, sujeito a qualquer restrio que voc pretende impor. Para obter mais informaes sobre como usar provedores de contedo, consulte a documentao de provedores de contedo.

Utilizando preferncias compartilhadas


A classe SharedPreferences fornece um framework geral que permite salvar e recuperar pares chave-valor persistente de tipos de dados primitivos. Voc pode usar SharedPreferences para salvar os dados primitivos: booleans, floats, inteiros, longos, e

ANDROID, uma viso geral Anderson Duarte de Amorim

201

strings. Estes dados vo persistir nas sesses de usurio (mesmo se sua aplicao morta). Para obter um objeto SharedPreferences para sua aplicao, use um dos dois mtodos: getSharedPreferences() - Use esta opo se voc precisa de arquivos de mltiplas preferncias

Preferncias do usurio
Preferncias compartilhadas no so estritamente para o salvar "as preferncias do usurio", como o toque de um usurio escolheu. Se voc est interessado em criar preferncias do usurio para seu aplicativo, consulte PreferenceActivity , que estabelece um quadro de atividades para voc criar as preferncias do usurio, persistido o qual (usando ser as

identificados pelo nome, que voc especifica primeiro. getPreferences() - Use esta opo se voc s precisa de um arquivo de com o parmetro

automaticamente

preferncias compartilhadas).

preferncias para a sua actividade. Porque este ser o nico arquivo de preferncias para sua atividade, voc no fornece um nome. Para escrever os valores: 1. Chame edit() para obter uma SharedPreferences.Editor. 2. Adicione valores com mtodos como putBoolean() e putString(). 3. Empregue os novos valores com commit(). Para ler os valores, use mtodos SharedPreferences como getBoolean() e getString(). Aqui est um exemplo que salva uma preferncia para o modo silencioso keypress em uma calculadora:
public class Calc extends Activity { public static final String PREFS_NAME = "MyPrefsFile"; @Override protected void onCreate(Bundle state){ super.onCreate(state); ... // Restore preferences SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); boolean silent = settings.getBoolean("silentMode", false); setSilent(silent); }

ANDROID, uma viso geral Anderson Duarte de Amorim

202

@Override protected void onStop(){ super.onStop(); // We need an Editor object to make preference changes. // All objects are from android.context.Context SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean("silentMode", mSilentMode); // Commit the edits! editor.commit(); } }

Usando o armazenamento interno


Voc pode salvar arquivos diretamente na memria interna do dispositivo. Por padro, os arquivos salvos no armazenamento interno so privados para sua aplicao e outras aplicaes no podem acess-los (nem mesmo o usurio). Quando o usurio desinstala o aplicativo, esses arquivos so removidos. Para criar e gravar um arquivo privado para o armazenamento interno: 1. Chame openFileOutput() com o nome do arquivo e o modo de funcionamento. Isso retorna um FileOutputStream. 2. Escreva no arquivo com o write(). 3. Feche o fluxo com close(). Por exemplo:
String FILENAME = "hello_file"; String string = "hello world!"; FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write(string.getBytes()); fos.close();

MODE_PRIVATE ir criar o arquivo (ou substituir um arquivo de mesmo nome) e torn-lo privado para sua aplicao. Outras modalidades disponveis so:

MODE_APPEND, MODE_WORLD_READABLE e MODE_WORLD_WRITEABLE.

ANDROID, uma viso geral Anderson Duarte de Amorim

203

Para ler um arquivo de armazenamento interno: 1. Chame openFileInput() e passe o nome do arquivo a ser lido. Isso retorna um FileInputStream. 2. Leia os bytes do arquivo com a read(). 3. Em seguida, feche o fluxo com close(). Dica: Se voc quiser salvar um arquivo esttico em seu aplicativo em tempo de compilao, salve o arquivo no diretrio de res/raw/ do seu projeto. Voc pode abri-lo com openRawResource(), passando a identificao de recurso R.raw.<filename>. Esse mtodo retorna um InputStream que voc pode usar para ler o arquivo (mas voc no pode escrever no arquivo original).

Salvando os arquivos de cache


Se voc gostaria de gravar alguns dados em cache, ao invs de armazen-lo persistentemente, voc deve usar getCacheDir() para abrir um arquivo que representa o diretrio interno onde a sua aplicao deve salvar os arquivos de cache temporrio. Quando o dispositivo est com pouco espao de armazenamento interno, o Android pode excluir esses arquivos de cache para recuperar espao. No entanto, voc no deve confiar no sistema para limpar esses arquivos para voc. Voc deve sempre manter os arquivos de cache e manter dentro de um limite razovel de espao consumido, como 1MB. Quando o usurio desinstala o aplicativo, esses arquivos so removidos. Outros mtodos teis: getFilesDir() Obtm o caminho absoluto para o diretrio de arquivos onde os arquivos internos so salvos. getDir() Cria (ou abre um existente) diretrio dentro de seu espao de armazenamento interno. deleteFile() Exclui um arquivo salvo na memria interna.

ANDROID, uma viso geral Anderson Duarte de Amorim

204

fileList() Retorna uma matriz de arquivos atualmente salvos pela sua aplicao.

Usando o armazenamento externo


Cada dispositivo compatvel com o Android suporta um "armazenamento externo" compartilhado que voc pode usar para salvar arquivos. Pode ser uma mdia de armazenamento removvel (como um carto SD) ou uma memria interna (no removvel). Os arquivos salvos no armazenamento externos so de leitura e podem ser modificados pelo usurio quando permitem armazenamento em massa USB para transferir arquivos de um computador. Ateno: os arquivos externos podem desaparecer se o usurio monta o armazenamento externo em um computador ou remove a mdia, e no h nenhuma segurana aplicada sobre os arquivos que voc salva para o armazenamento externo. Todas as aplicaes podem ler e gravar arquivos colocados no armazenamento externo e o usurio pode remov-los.

Verificar a disponibilidade dos meios


Antes de fazer qualquer trabalho com o armazenamento externo, voc deve sempre chamar getExternalStorageState() para verificar se os meios de comunicao esto disponveis. A mdia pode ser montada a um computador, faltando, somente leitura, ou em algum outro estado. Por exemplo, aqui est como voc pode verificar a disponibilidade:
boolean mExternalStorageAvailable = false; boolean mExternalStorageWriteable = false; String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // We can read and write the media mExternalStorageAvailable = mExternalStorageWriteable = true; } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // We can only read the media mExternalStorageAvailable = true; mExternalStorageWriteable = false; } else { // Something else is wrong. It may be one of many other states, but all we need // to know is we can neither read nor write mExternalStorageAvailable = mExternalStorageWriteable = false; }

ANDROID, uma viso geral Anderson Duarte de Amorim

205

Este exemplo verifica se o armazenamento externo est disponvel para ler e escrever. O mtodo getExternalStorageState() retorna outros estados que voc pode querer verificar, como se a mdia est sendo compartilhada (conectada a um computador), est totalmente ausente, foi mal removida, etc. Voc pode us-los para notificar o usurio com mais informaes quando o aplicativo precisa de acesso mdia.

Acessando arquivos em armazenamento externo


Se voc estiver usando a API de nvel 8 ou superior, use getExternalFilesDir() para abrir um arquivo que representa o diretrio de armazenamento externo onde voc deve salvar seus arquivos. Este mtodo utiliza um parmetro type que especifica o tipo de subdiretrio que voc deseja, como DIRECTORY_MUSIC e

DIRECTORY_RINGTONES (passe null para receber a raiz do diretrio do arquivo da aplicativo). Este mtodo ir criar o diretrio apropriado, se necessrio. Ao especificar o tipo de diretrio, voc garante que a mdia scanner do Android ir categorizar corretamente seus arquivos no sistema (por exemplo, os ringtones so identificados como toques, e no msica). Se o usurio desinstala o aplicativo, este diretrio e todo seu contedo sero apagados. Se voc estiver usando a API de nvel 7 ou inferior, use getExternalStorageDirectory() para abrir um File que representa a raiz de armazenamento externo. Voc deve ento escrever os seus dados no seguinte diretrio: /Android/data/<package_name>/files/ O <package_name> o seu nome de estilo do pacote Java, tal como "com.example.android.app". Se o dispositivo do usurio est executando API nvel 8 ou superior e desinstalar o aplicativo, este diretrio e todo seu contedo sero apagados.

Como salvar arquivos que Escondendo seus arquivos a partir da devem ser compartilhados Media Scanner
Se voc deseja salvar os arquivos que no so especficos para a sua aplicao e que no devem ser excludos quando o aplicativo desinstalado, salva-os em um dos
Inclua um arquivo vazio chamado .nomedia em seu diretrio de arquivos externos (note o ponto prefixo ao nome do arquivo). Isto ir prevenir o media scanner do Android de ler arquivos de mdia e inclu-los em aplicativos como Galley ou Music.

ANDROID, uma viso geral Anderson Duarte de Amorim

206

diretrios pblicos de armazenamento externo. Esses diretrios esto na origem do armazenamento externo, como Music/, Pictures/, Ringtones/ e outros. Na API nvel 8 ou superior, use getExternalStoragePublicDirectory(),passando para ele o tipo de diretrio pblico que deseja, tais como DIRECTORY_MUSIC, DIRECTORY_PICTURES, DIRECTORY_RINGTONES ou outros. Este mtodo ir criar o diretrio apropriado, se necessrio. Se voc estiver usando a API de nvel 7 ou inferior, use getExternalStorageDirectory() para abrir um File que representa a raiz do armazenamento externo, em seguida, salve seus arquivos compartilhados em um dos seguintes diretrios: Music/ - o scanner media classifica todas as mdias encontradas aqui como a msica do usurio. Podcasts/ - scanner media classifica todas as mdias encontradas aqui como um podcast. Ringtones/ - scanner media classifica todas as mdias encontradas aqui como um ringtone. Alarms/ - scanner media classifica todas as mdias encontradas aqui como um som de alarme. Notifications/ - scanner media classifica todas as mdias encontradas aqui como um som de notificao. Pictures/ - todas as fotos (excluindo as tiradas com a cmera). Movies/ - todos os filmes (excluindo aqueles filmados com a cmera de vdeo). Download/ - downloads diversos.

Salvando os arquivos de cache


Se voc estiver usando a API de nvel ou superior, use 8 getExternalCacheDir() para abrir um File que representa o diretrio de armazenamento externo, onde voc deve salvar os arquivos de cache. Se o usurio desinstala o aplicativo, esses arquivos sero automaticamente excludos. No entanto, durante a vida do seu aplicativo, voc deve gerenciar esses arquivos de cache e eliminar os que no so necessrios, a fim de preservar o espao do arquivo.

ANDROID, uma viso geral Anderson Duarte de Amorim

207

Se voc estiver usando a API de nvel 7 ou inferior, use getExternalStorageDirectory() para abrir um File que representa a raiz do armazenamento externo, em seguida, escreva o seu cache de dados no seguinte diretrio: /Android/data/<package_name>/cache/ O <package_name> o seu estilo nome do pacote Java, tal qual

"com.example.android.app".

Utilizando bancos de dados


Android oferece suporte completo para bancos de dados SQLite. Qualquer banco de dados que voc criar sero acessveis pelo nome de qualquer classe na aplicao, mas no fora da aplicao. O mtodo recomendado para criar um novo banco de dados SQLite criar uma subclasse de SQLiteOpenHelper e substituir o mtodo onCreate(), no qual voc pode executar um comando SQLite para criar tabelas no banco de dados. Por exemplo:
public class DictionaryOpenHelper extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 2; private static final String DICTIONARY_TABLE_NAME = "dictionary"; private static final String DICTIONARY_TABLE_CREATE = "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" + KEY_WORD + " TEXT, " + KEY_DEFINITION + " TEXT);"; DictionaryOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DICTIONARY_TABLE_CREATE); } }

Voc pode obter uma instncia de sua implementao SQLiteOpenHelper usando o construtor que voc definiu. Para escrever e ler a partir do banco de dados, chame getWritableDatabase() e getReadableDatabase(), respectivamente. Estes devolvem um objeto SQLiteDatabase que representa o banco de dados e fornece mtodos para operaes de SQLite.

ANDROID, uma viso geral Anderson Duarte de Amorim

208

Voc pode executar consultas SQLite usando mtodos query() SQLiteDatabase, que aceitam parmetros de consulta diversos, tais como a tabela a ser consultada, a projeo, seleo, colunas,

Android

no

impe

qualquer

limitao para alm dos conceitospadro SQLite. Ns

recomendamos incluir um valor de campo autoincrementado como chave que pode ser usado como

agrupamento e outros. Cada consulta SQLite ir retornar um Cursor que aponta para todos os registros encontrados pela consulta. O Cursor sempre o mecanismo com o qual voc pode navegar pelos resultados de uma consulta de banco de dados e ler linhas e colunas. Para aplicativos de exemplo que demonstram como usar banco de dados SQLite no Android, consulte as aplicaes Note Pad e Dicionrio pesquisvel.

uma

identificao

nica

para

localizar rapidamente um registro. Isso no necessria para dados privados, implementar mas um se provedor voc de

contedo, voc deve incluir uma identificao exclusiva com a constante BaseColumns._ID.

Banco de dados de depurao


O Android SDK inclui uma ferramenta sqlite3 de banco de dados que permite que voc navegue sobre o contedo da tabela, execute comandos SQL e execute outras funes teis em bancos de dados SQLite.

Usando uma conexo de rede


Voc pode usar a rede (quando disponvel) para armazenar e recuperar dados sobre os seus prprios servios baseados na web. Para fazer operaes de rede, use as classes dos seguintes pacotes: java.net.* android.net.*

ANDROID, uma viso geral Anderson Duarte de Amorim

209

Artigos Acessibilidade
Linguagens e recursos
Text-to-Speech TTS: tambm conhecido como speech synthesis (sntese de fala, em portugus) um recurso disponibilizado a partir de Android 1.6 (API Level 4) que possibilita ao dispositivo ler textos em diversas linguagens. O mecanismo TTS embarcado no Android suporta ingls (britnico ou americano), francs, alemo, italiano e espanhol e precisa saber qual idioma pronunciar para adequar a voz, afinal, uma mesma palavra possui pronuncias diferentes dependendo da lngua. Uma checagem da disponibilidade do recurso se faz necessrio tendo em vista que, apesar de todos os dispositivos com Android terem a funcionalidade embarcada, alguns possuem armazenamento limitado e pode ser que faltem arquivos de recursos especficos do idioma, sendo assim, o seguinte cdigo verifica a presena dos recursos TTS.
Intent checkIntent = new Intent(); checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);

Uma checagem que retorna sucesso marcada por CHECK_VOICE_DATA_PASS indicando que o dispositivo est pronto para falar, depois da criao do objeto TextToSpeech. Em caso negativo, o dispositivo ir utilizar o ACTION_INSTALL_TTS_DATA que dispara uma ao levando o usurio a fazer a instalao manualmente acessando o Android Market; A instalao feita automaticamente aps a concluso do download. Uma implementao da verificao do resultado da checagem est abaixo:
private TextToSpeech mTts; protected void onActivityResult( int requestCode, int resultCode, Intent data) { if (requestCode == MY_DATA_CHECK_CODE) { if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { // success, create the TTS instance mTts = new TextToSpeech(this, this); } else { // missing data, install it Intent installIntent = new Intent(); installIntent.setAction( TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(installIntent);

ANDROID, uma viso geral Anderson Duarte de Amorim

210

} }}

No construtor da instncia TextToSpeech ns passamos uma referncia ao Contexto a ser usado (neste caso a atividade atual), e um OnInitListener (aqui a nossa atividade tambm). Dessa forma habilitado para que a aplicao seja notificada quando o TextTo-Speech totalmente carregado, ento podemos comear a configurar-lo e us-lo.

Linguagens e localidade
No Google I/O 2009 foi mostrado uma utilizao do TTS para falar o resultado de uma traduo de e para uma das lnguas disponveis. Um exemplo de chamada como o abaixo:
mTts.setLanguage(Locale.US);

Ou para verificar se uma linguagem est disponvel, basta usar o trecho abaixo que retornar TextToSpeech.LANG_COUNTRY_AVAILABLE para indicar que o idioma e o pas, como descrito pelo parmetro de localidade, so suportados (e os dados esto corretamente instalados), como tambm pode retornar

TextToSpeech.LANG_AVAILABLE indicando que a lngua est disponvel ou o oposto TextToSpeech.LANG_MISSING_DATA.


mTts.isLanguageAvailable(Locale.UK)) mTts.isLanguageAvailable(Locale.FRANCE)) mTts.isLanguageAvailable(new Locale("spa", "ESP")))

Obs.: para usar o cdigo Locale.getDefault(), deve-se certificar primeiramente se o idioma padro suportado.

Fazendo o dispositivo falar


A maneira mais simples de fazer isso usando o mtodo speak() como:
String myText1 = "Did you sleep well?"; String myText2 = "I hope so, because it's time to wake up."; mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, null); mTts.speak(myText2, TextToSpeech.QUEUE_ADD, null);

O mecanismo TTS gerencia uma fila global de todas as entradas para sintetizar, que tambm so conhecidos como "expresses". Cada TextToSpeech pode gerir sua prpria fila a fim de controlar o que vai interromper a emisso atual e que simplesmente uma fila de espera.

ANDROID, uma viso geral Anderson Duarte de Amorim

211

No Android, cada stream de udio que reproduzido est associado a um tipo de fluxo, tal como definido no android.media.AudioManager . Para um despertador falando, o texto a ser reproduzido pertence ao tipo de fluxo AudioManager.STREAM_ALARM, para que ele respeite as definies de alarme que o usurio escolheu no dispositivo. O ltimo parmetro do mtodo speak() permite que voc passe para os parmetros do TTS, especificado como pares chave / valor em um HashMap, tal qual:
HashMap<String, String> myHashAlarm = new HashMap(); myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM)); mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm); mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);

Como as chamadas so assncronas, pode ser necessrio identificar se uma sntese foi concluda, isso pode ser feito da seguinte forma:
mTts.setOnUtteranceCompletedListener(this); myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM)); mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm); myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "end of wakeup message ID"); // myHashAlarm now contains two optional parameters mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);

E a atividade notificada pelo mtodo, repare que a mensagem foi usada para ser identificada no mtodo:
public void onUtteranceCompleted(String uttId) { if (uttId == "end of wakeup message ID") { playAnnoyingMusic(); } }

Como o recurso de fala exige bastante processamento, numa situao em que um determinado texto ser lido diversas vezes mais interessante gravar o udio para ser reproduzido posteriormente.
HashMap<String, String> myHashRender = new HashMap(); String wakeUpText = "Are you up yet?"; String destFileName = "/sdcard/myAppCache/wakeUp.wav"; myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, wakeUpText); mTts.synthesizeToFile(wakuUpText, myHashRender, destFileName);

A funcionalidade de text-to-speech depende de um servio dedicado compartilhado entre todos os aplicativos que usam esse recurso. Quando voc terminar de usar o TTS, use a instruo mTts.shutdown() dentro do mtodo onDestroy(), por exemplo. ANDROID, uma viso geral Anderson Duarte de Amorim
212

Interface
Toque
O modo de toque um estado da hierarquia de vista que depende unicamente da interao do usurio com o telefone. Por si s, o modo de tocar algo muito fcil de entender, pois ele simplesmente indica se a interao do usurio passado foi realizada com a tela sensvel ao toque. Por exemplo, se voc estiver usando um dispositivo com Android, a seleo de um widget com o trackball vai lev-lo sair do modo de tocar, no entanto, se voc toca um boto na tela com seu dedo, voc entrar no modo de tocar. Quando o usurio no estiver em modo de tocar, ns falamos sobre o modo de trackball, o modo de navegao ou a navegao por teclado, por isso no se surpreenda se voc encontrar esses termos. Existe apenas uma API diretamente relacionada com o modo de toque, View.isInTouchMode(). Curiosamente, o modo de tocar enganosamente simples e as conseqncias de entrar no modo de tocar muito maior do que voc imagina. Vejamos algumas das razes. Toque em modo de seleo e foco Criar um conjunto de ferramentas UI para dispositivos mveis difcil porque so vrios os mecanismos de interao. Alguns dispositivos oferecem apenas 12 teclas, algumas tm uma tela sensvel ao toque, alguns exigem uma caneta, alguns tm ambos um ecr tctil e um teclado. Com base nos recursos de hardware do usurio, ele pode interagir com seu aplicativo usando mecanismos diferentes, ento tivemos que pensar muito sobre todos os possveis problemas que possam surgir. Uma questo nos levou a criar o modo de toque. Imagine um aplicativo simples, ApiDemos por exemplo, que mostra uma lista de itens de texto. O usurio pode navegar livremente pela lista usando a trackball, mas tambm, em alternativa, deslocar e arremessar a lista usando a tela sensvel ao toque. O problema neste cenrio como lidar com a seleo corretamente quando o usurio manipula a lista atravs da tela sensvel ao toque. Neste caso, se o usurio selecionar um item no topo da lista e ento arremessa a lista para o fundo, o que deve acontecer com a seleo? E se ele permanecer no item e rolar

ANDROID, uma viso geral Anderson Duarte de Amorim

213

para fora da tela? O que deve acontecer se o usurio decidiu ento mover a seleo com o trackball? Ou pior, o que deve acontecer se o usurio pressiona o trackball para agir de acordo com o item selecionado, que no mostrado na tela mais? Aps cuidadosa considerao, decidimos remover por completo a seleo, quando o usurio manipula a interface do usurio atravs da tela sensvel ao toque. No modo de toque, no h foco e no h seleo. Qualquer item selecionado em uma lista de em uma grade fica desmarcada, logo que o usurio entra no modo de tocar. Da mesma forma, quaisquer widgets ficaram desfocados quando o usurio entra no modo de tocar. A imagem abaixo ilustra o que acontece quando o usurio toca uma lista depois de selecionar um item com o trackball.

Para tornar as coisas mais naturais para o usurio, o quadro sabe como ressuscitar a seleo / foco sempre que o usurio sai do modo de tocar. Por exemplo, se o usurio fosse usar o trackball novamente, a seleo iria reaparecer no item previamente selecionado. por isso que alguns desenvolvedores esto confusos quando se criar uma exibio personalizada e comear a receber os principais eventos s depois de mover o trackball uma vez: a sua aplicao est no modo de tocar, e eles precisam usar o trackball para sair do modo de tocar e ressuscitar o foco.

ANDROID, uma viso geral Anderson Duarte de Amorim

214

A relao entre o modo de toque, seleo e foco significa que voc no deve confiar na seleo e/ou foco existir em sua aplicao. Um problema muito comum com o Android para novos desenvolvedores contar com ListView.getSelectedItemPosition(). No modo de toque, este mtodo retornar INVALID_POSITION. Focando no modo Touch Em geral, o foco no existe no modo de tocar. No entanto, o foco pode existir no modo de tocar em uma maneira muito especial chamado focusable. Este modo especial foi criado para widgets que recebem a entrada de texto, como EditText ou ListView. O modo focusable o que permite ao usurio inserir texto dentro de um campo de texto na tela, sem primeiro selecion-la com a bola ou o dedo. Quando um usurio toca a tela, o aplicativo ir entrar no modo de toque se ele no estava no modo de tocar j. O que acontece durante a transio para o modo de tocar depende do que o usurio tocou, e que atualmente tem foco. Se o usurio toca um widget que focusable no modo de tocar, o widget ir receber o foco. Caso contrrio, qualquer elemento ao qual se dedica atualmente no vai manter o foco a menos que seja focusable no modo de tocar. Por exemplo, na figura abaixo, quando o usurio toca a tela, o campo de texto recebe o foco. Focusable no modo de uma propriedade que voc pode definir a si mesmo, seja de cdigo ou de XML. No entanto, voc deve us-lo com parcimnia e s em situaes muito especficas, porque quebra a coerncia com o comportamento normal da interface do Android. Um jogo um bom exemplo de uma aplicao que pode fazer bom uso do focusable na propriedade de modo sensvel ao toque. MapView, se usada em tela cheia como no Google Maps, outro bom exemplo de onde voc pode usar focusable no modo de tocar

corretamente. Abaixo est um exemplo de um widget focusable em modo de tocar. Quando o usurio bate um AutoCompleteTextView com o dedo, o foco permanece no campo de texto de entrada:

ANDROID, uma viso geral Anderson Duarte de Amorim

215

Novos desenvolvedores para o Android, muitas vezes pensam que focusable no modo de tocar a soluo que eles precisam para "consertar" o problema do "desaparecimento" da seleo/foco. Ns encorajamos voc a pensar muito antes de utiliz-lo. Se usada incorretamente, pode fazer seu aplicativo se comportar de maneira diferente do resto do sistema e simplesmente jogar fora os hbitos do usurio. O quadro Android contm todas as ferramentas necessrias para lidar com as interaes do usurio sem usar focusable no modo de tocar. Por exemplo, em vez de tentar fazer ListView sempre manter a sua seleo, basta usar o modo de escolha apropriada, como mostrado na setChoiceMode(int) .

Gestos
As telas de toque so uma tima maneira de interagir com aplicaes em dispositivos mveis. Com uma tela de toque, os usurios podem facilmente tocar, arrastar,

arremessar ou deslizar rapidamente e realizar aes em seus aplicativos favoritos. Para os desenvolvedores de aplicativos o Android faz com que seja fcil reconhecer aes simples, mas tem sido mais difcil de lidar com gestos complicados, s vezes exigindo que os desenvolvedores escrevam um monte de cdigo. por isso que foi introduzida uma nova API de gestos no Android 1.6. Esta API, localizada no novo pacote android.gesture , permite armazenar, carregar, desenhar e reconhecer gestos. Clique para baixar o cdigo fonte dos exemplos

Mtodo de entrada de dados


A partir do Android 1.5, a plataforma Android oferece um Input Method Framework (FMI) que permite a criao de mtodos de entrada na tela, como teclados virtuais. Este artigo fornece uma viso geral de editores de mtodo de Android de entrada (IME) e o que um aplicativo precisa fazer para trabalhar bem com eles. O FMI concebido para

ANDROID, uma viso geral Anderson Duarte de Amorim

216

apoiar novas classes de dispositivos Android, como os teclados sem hardware, por isso importante que o aplicativo funcione bem com o FMI e oferece uma tima experincia para os usurios. O que um mtodo de entrada? O FMI Android foi concebido para suportar uma variedade de IMEs, incluindo o teclado virtual, reconhecedores de mo-escrita, e tradutores teclado duro. Nosso foco, no entanto, ser em teclados virtuais, j que este o tipo de mtodo de entrada que atualmente faz parte da plataforma. Um usurio normalmente ir acessar o IME atual, tocando em uma exibio de texto para editar, conforme mostrado na tela inicial:

O teclado virtual posicionado na parte inferior da tela sobre a janela do aplicativo. Para organizar o espao disponvel entre a aplicao e o IME, usamos algumas abordagens, a que mostrada aqui chamado de pan e digitalizar, e simplesmente envolve a rolagem da janela do aplicativo em torno de modo que a viso focada atualmente visvel. Este o modo padro, pois mais seguro para as aplicaes existentes.

ANDROID, uma viso geral Anderson Duarte de Amorim

217

Na maioria das vezes o layout da tela um resize, onde a janela da aplicao redimensionada para ser totalmente visvel. Um exemplo mostrado aqui, quando escrevo uma mensagem de e-mail:

O tamanho da janela do aplicativo alterada para que nenhum deles seja escondido pelo IME, permitindo acesso total ao aplicativo e IME. Isto, obviamente, s funciona para aplicativos que tm uma rea redimensionvel que pode ser reduzida para dar espao suficiente, mas o espao vertical neste modo realmente nada menos do que o que est disponvel na orientao paisagem. O principal modo final fullscreen ou modo de extrato. Isso usado quando o IME muito grande para o espao compartilhar com a aplicao de base. Com o IME padro, voc s vai encontrar essa situao quando a tela est em uma orientao horizontal, embora IMEs sejam livres para us-lo sempre que desejarem. Neste caso, a janela da aplicao deixada como est, e simplesmente o IME exibe a tela inteira em cima dela, como mostrado aqui:

ANDROID, uma viso geral Anderson Duarte de Amorim

218

Porque o IME est cobrindo o aplicativo, ele tem a sua rea de edio prpria, o que mostra o texto, na verdade contida na petio inicial. Existem tambm algumas oportunidades limitadas aplicao que tem que personalizar as partes do IME para melhorar a experincia do usurio. Atributos bsicos XML para controlar IMEs H uma srie de coisas que o sistema faz para tentar ajudar de trabalho existente com as aplicaes IMEs to bem quanto possvel, tais como: Use pan e scan por padro, a menos que possa razoavelmente supor que o modo de redimensionar vai trabalhar pela existncia de listas, percorrer as exibies, etc. Analisar no TextView vrios atributos existentes para adivinhar o tipo de contedo (nmeros, texto simples, senha, etc.) para ajudar o teclado a exibir um esquema de chave apropriado. Atribuir algumas aes padro para o IME fullscreen, como "campo prximo" e "feito". H tambm algumas coisas simples que voc pode fazer na sua aplicao que, muitas vezes, melhoram significativamente sua experincia de usurio. Exceto quando mencionado explicitamente, estes iro trabalhar em qualquer verso da plataforma Android, mesmo os anteriores para o Android 1.5 (uma vez que ir simplesmente ignorar essas novas opes). Especificando cada tipo de controle de entrada EditText A coisa mais importante para um pedido a fazer usar o novo atributo android:inputType em cada EditText. O atributo fornece informao muito mais rica

ANDROID, uma viso geral Anderson Duarte de Amorim

219

sobre o contedo do texto. Este atributo realmente substitui muitos atributos existentes ( android: password , android: singleLine , android: numeric , android: phoneNumber , android: capitalize , android: autoText e android: editable). Se voc especificar os atributos mais velhos e os novos android:inputType, o sistema usa android:inputType e ignora as outras. O android:inputType atributo tem trs partes: A classe a interpretao geral de caracteres. As classes atualmente suportadas so text (plain text), number (nmero decimal), phone (nmero de telefone), e datetime (uma data ou hora). A variao um refinamento da classe. No atributo, normalmente voc vai especificar a classe e variante juntamente com a classe como um prefixo. Por exemplo, textEmailAddress um campo de texto onde o usurio ir inserir algo que um endereo de correio (foo@bar.com) para a disposio das teclas ter um @ "carter" de acesso fcil, e numberSigned um campo numrico com um sinal. Se somente a classe especificado, ento voc obtm o padro / variante genrica. Sinalizadores adicionais podem ser especificados de abastecimento de refinamento. Esses sinalizadores so especficos para uma classe. Por exemplo, alguns sinalizadores para o text de classe so textCapSentences, textAutoCorrect e textMultiline. Como exemplo, aqui o EditText novo para a aplicao do IM ver texto da mensagem:
<EditText android:id="@+id/edtInput" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine" android:imeOptions="actionSend|flagNoEnterAction" android:maxLines="4" android:maxLength="2000" android:hint="@string/compose_hint"/>

Ativar o modo de redimensionamento e funcionalidades outra janela A segunda coisa mais importante para sua aplicao a fazer especificar o comportamento global da sua janela em relao ao mtodo de entrada. O aspecto mais

ANDROID, uma viso geral Anderson Duarte de Amorim

220

visvel disto o controle redimensionar VS. pan e scan mode, mas existem outras coisas que voc pode fazer bem para melhorar sua experincia de usurio. Voc normalmente ir controlar esse comportamento atravs do

android:windowSoftInputMode em cada <activity> em sua AndroidManifest.xml. Como o tipo de entrada, h um par de peas diferentes de dados que pode ser especificado aqui, combinando-as entre si: O modo de ajuste da janela especificado com adjustResize ou adjustPan . altamente recomendado que voc especifique sempre um ou outro. Voc ainda pode controlar se o IME ser exibido automaticamente quando sua atividade exibida e outras situaes onde o usurio move a ele. O sistema no mostrar automaticamente um IME, por padro, mas em alguns casos pode ser conveniente para o usurio se uma aplicao permite esse comportamento. Voc pode solicitar este com stateVisible . H tambm um nmero de opes de outro estado para o controle mais detalhado que voc pode encontrar na documentao. Um exemplo tpico desse campo pode ser visto na atividade de edio do contato, o que garante que ele redimensionado e exibe automaticamente o IME para o usurio:
<activity name="EditContactActivity" android:windowSoftInputMode="stateVisible|adjustResize"> ... </activity>

Controlando os botes de ao Para a personalizao final, vamos olhar para a "ao" de botes no IME. Existem atualmente dois tipos de aes: A tecla enter em um teclado virtual normalmente ligada a uma ao quando no estiverem operando em um multi-line de edio de texto. Quando em modo de tela cheia, um IME pode tambm colocar um boto de ao adicional direita do texto que est sendo editado, dando ao usurio o acesso rpido a uma operao de aplicativos comuns.

ANDROID, uma viso geral Anderson Duarte de Amorim

221

Estas opes so controladas com o atributo android:imeOptions em TextView . O valor que voc fornecer aqui pode ser qualquer combinao de: Uma das aes pr-definidas constantes ( actionGo , actionSearch , actionSend , actionNext , actionDone ). Se nenhum desses for especificado, o sistema ir inferir qualquer actionNext ou actionDone dependendo se h um campo focusable aps este, voc pode explicitamente forar a nenhuma ao com actionNone. O flagNoEnterAction informa o IME que a ao no deve estar disponvel na tecla enter, mesmo que o texto em si no multi-linha. Isso evita ter aes irrecuperveis (enviar) que pode ser tocado acidentalmente pelo usurio durante a digitao. O flagNoAccessoryAction remove o boto de ao da rea de texto, deixando mais espao para o texto. O flagNoExtractUi remove completamente a rea de texto, permitindo que o aplicativo possa ser visto por trs dele. A anterior mensagem de aplicao MI tambm fornece um exemplo de um uso interessante da imeOptions, para especificar a ao de envio, mas no que seja mostrado a tecla Enter:
android:imeOptions="actionSend|flagNoEnterAction"

APIs para controlar IMEs Para um controle mais avanado sobre o IME, h uma variedade de novas APIs que voc pode usar. A menos que tenha um cuidado especial (como por meio de reflexo), utilizando essas APIs far com que seu aplicativo seja incompatvel com as verses anteriores do Android, e voc deve se certificar de que voc especifique android:minSdkVersion="3" em seu manifesto. A API principal o novo android.view.inputmethod.InputMethodManager, que voc pode recuperar com Context.getSystemService(). Ele permite que voc interaja com o estado global do mtodo de entrada, como explicitamente esconder ou mostrar a rea atual do IME de entrada.

ANDROID, uma viso geral Anderson Duarte de Amorim

222

H tambm novas bandeiras controlando a interao do mtodo de entrada, que voc pode controlar atravs da A existente classe Window.addFlags() acrescentou e novos mtodos

Window.setSoftInputMode().

PopupWindow

correspondentes para controlar essas opes em sua janela. Uma coisa em particular a ter em conta o novo

WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, que usado para controlar se uma janela est em cima ou atrs do IME atual. A maior parte da interao entre um IME ativos e a aplicao feita atravs do android.view.inputmethod.InputConnection. Esta a API implementada em uma aplicao, que um IME chama para realizar as operaes de edio apropriada sobre o pedido. Voc no vai precisar se preocupar com isso, pois TextView oferece sua prpria implementao para si mesmo. H tambm um punhado de novas View s APIs, a mais importante delas sendo onCreateInputConnection() que cria um novo InputConnection de um IME (e preenche um android.view.inputmethod.EditorInfo com o seu tipo de entrada, as opes IME, e outros dados), novamente, a maioria dos desenvolvedores no precisaro se preocupar com isso, pois TextView cuida disso para voc.

Criando um mtodo de entrada de dados


Para criar um mtodo de entrada (IME) para inserir texto em campos de texto e outras exibies, voc precisa estender a classe InputMethodService. Essa classe fornece grande parte da implementao de base para um mtodo de entrada, em termos de administrar o estado e a visibilidade do mtodo de entrada e se comunicar com a atividade visvel no momento. O tpico ciclo de vida de um InputMethodService:

ANDROID, uma viso geral Anderson Duarte de Amorim

223

ANDROID, uma viso geral Anderson Duarte de Amorim

224

Campos de um aplicativo de texto podem ter diferentes tipos de entrada especificada sobre eles, como o texto de forma livre, numrico, URL, endereo de e-mail e busca. Quando voc implementa um novo mtodo de entrada, voc precisa estar ciente dos tipos de entrada diferentes. Os mtodos de entrada no so automaticamente comutados para diferentes tipos de entrada e por isso necessrio para suportar todos os tipos no IME. No entanto, o IME no responsvel por validar a entrada enviada para o aplicativo. Essa a responsabilidade da aplicao. Por exemplo, o LatinIME equipados com a plataforma Android oferece layouts diferentes para o texto e entrada de nmero de telefone:

Preste ateno especfica ao enviar o texto para campos de senha. Certifique-se que a senha no visvel na sua interface do usurio - nem no modo de exibio de entrada ou o ponto de vista dos candidatos. Alm disso, no salvar a senha em qualquer lugar sem explicitamente informar o utilizador. A interface do usurio deve ser capaz de escala entre as orientaes retrato e paisagem. No modo IME no fullscreen, deixar espao suficiente para a aplicao para mostrar o campo de texto e qualquer contexto associado. De preferncia, no mais que metade da tela deve ser ocupada pelo IME. Existem duas maneiras de enviar mensagens de texto para o aplicativo. Voc pode enviar individuais eventos-chave ou voc pode editar o texto ao redor do cursor no campo a aplicao do texto. Para enviar um evento-chave, voc pode simplesmente construir objetos KeyEvent e chamar InputConnection.sendKeyEvent(). Aqui esto alguns exemplos:
InputConnection ic = getCurrentInputConnection(); long eventTime = SystemClock.uptimeMillis(); ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,

ANDROID, uma viso geral Anderson Duarte de Amorim

225

KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0, KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)); ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0, KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));

Ou ento use o seguinte comando:


InputMethodService.sendDownUpKeyEvents(keyEventCode);

Ao editar texto em um campo de texto, alguns dos mtodos mais teis na android.view.inputmethod.InputConnection so: getTextBeforeCursor() getTextAfterCursor() deleteSurroundingText() commitText()

Aes de desenhos
Drawable Mutations uma classe para oferecer ao programador algo que pode ser desenhado (Drawable Mutations). Por exemplo, um BitmapDrawable usado para exibir imagens, um ShapeDrawable para desenhar formas e gradientes e assim por diante. Voc pode at mesmo combinlas para criar renderizaes complexas. Por exemplo, toda vez que voc criar um Button, uma nova drawable carregada a partir do quadro de recursos ( android.R.drawable.btn_default ). Isto significa que todos os botes em todos os aplicativos usam uma instncia diferente drawable como pano de fundo. No entanto, todas estas partes drawables possuem um estado comum, o

chamado "estado constante". O contedo deste estado varia de acordo com o tipo de drawable voc est usando, mas, geralmente, contm todas as propriedades que podem ser definidos por um recurso. No caso de um boto, o constante estado contm uma imagem bitmap. Desta forma, todos os botes em todos os aplicativos compartilham o mesmo bitmap, o que economiza um monte de memria. O diagrama abaixo mostra como as entidades so criadas quando voc atribuir o recurso de mesma imagem como fundo de dois pontos de vista diferentes. Como voc

ANDROID, uma viso geral Anderson Duarte de Amorim

226

pode ver dois drawables so criadas, mas que ambos compartilham o mesmo estado constante, portanto, a mesma bitmap:

Esse recurso de compartilhamento de estado de grande valia para evitar o desperdcio de memria, mas pode causar problemas quando voc tentar modificar as propriedades de um drawable. Imagine uma aplicao com uma lista de livros. Cada livro tem uma estrela ao lado de seu nome, totalmente opaco quando o usurio marca o livro como um dos favoritos, e translcido quando o livro no um favorito. Para conseguir esse efeito, voc provavelmente vai escrever o seguinte cdigo em seu mtodo adaptador de lista do getView():
Book = ...; TextView Item_da_lista = ...; listItem.setText (book.getTitle ()); estrela Drawable = context.getResources () getDrawable (R.drawable.star).; if (book.isFavorite ()) { star.setAlpha (255); / opaca / Else {} star.setAlpha (70); / translcido }

ANDROID, uma viso geral Anderson Duarte de Amorim

227

Infelizmente, este pedao de cdigo gera um resultado um pouco estranho: todas as drawables tm a mesma opacidade. Esse resultado explicado pela constante estado. Mesmo que ns estamos comeando uma nova instncia drawable para cada item da lista, o constante estado permanece o mesmo e, no caso de BitmapDrawable, a opacidade parte da constante estado. Assim, mudando a opacidade de uma instncia muda drawable a opacidade de todas as outras instncias. Android 1.5 e superior oferecem uma maneira muito fcil de resolver esse problema com a nova mutate() mtodo. Quando voc chamar esse mtodo em um drawable, a constante estado de drawable duplicada para permitir a voc alterar qualquer propriedade, sem afetar outros drawables. Note-se que os bitmaps so ainda comuns, mesmo depois de uma mutao drawable. O diagrama abaixo mostra o que acontece quando voc chama mutate() em um drawable:

ANDROID, uma viso geral Anderson Duarte de Amorim

228

Agora, o cdigo a ser escrito parecido com o abaixo.


Drawable star = context.getResources().getDrawable(R.drawable.star); if (book.isFavorite()) { star.mutate().setAlpha(255); // opaque } else { star. mutate().setAlpha(70); // translucent }

Assim, um exemplo se uso, como o citado acerca dos livros, fica como a figura abaixo.

Truques de layout: criando layouts eficientes


O Android UI Toolkit oferece diversos gerenciadores de layout que so bastante fceis de usar e, na maioria das vezes, voc s precisa das caractersticas bsicas destes gerenciadores de layout para implementar uma interface de usurio. Ater-se s caractersticas bsicas infelizmente no a forma mais eficiente para criar interfaces de usurio. Um exemplo comum o abuso de LinearLayout , o que leva a uma proliferao de pontos de vista e hierarquia de vista. Cada ponto de vista - ou pior, cada gerente de layout - que voc adicionar sua aplicao tem um custo: layout de inicializao, e o desenho se torna mais lento. A passagem de layout pode ser muito

ANDROID, uma viso geral Anderson Duarte de Amorim

229

cara principalmente quando voc aninhar diversos LinearLayout que utilizam o weight do parmetro, que requer que o nodo filho seja medido duas vezes. Consideremos um exemplo muito simples e comum de um esquema: um item da lista com um cone no lado esquerdo, um ttulo em cima e uma descrio opcional abaixo do ttulo.

Uma ImageView e dois TextView so posicionados em relao uns aos outros, aqui o wireframe do layout como capturado pelos HierarchyViewer :

A implementao desta estrutura simples com LinearLayout. O item em si uma LinearLayout horizontal com um ImageView e um LinearLayout vertical, que contm as duas TextView. Aqui est o cdigo fonte deste esquema:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginRight="6dip" android:src="@drawable/icon" /> <LinearLayout android:orientation="vertical" android:layout_width="0dip" android:layout_weight="1" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="0dip"

ANDROID, uma viso geral Anderson Duarte de Amorim

230

android:layout_weight="1" android:gravity="center_vertical" android:text="My Application" /> <TextView android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" android:singleLine="true" android:ellipsize="marquee" android:text="Simple application that shows how to use RelativeLayout" /> </LinearLayout> </LinearLayout>

Este esquema acima funciona, mas pode ser prejudicial se voc instanci-la para cada item da lista de um ListView . O mesmo esquema pode ser reescrito utilizando um nico RelativeLayout , salvando assim um ponto de vista, e melhor ainda, um nvel na hierarquia do ponto de vista, por item da lista. A implementao do layout com um RelativeLayout simples:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" android:layout_marginRight="6dip" android:src="@drawable/icon" /> <TextView android:id="@+id/secondLine" android:layout_width="fill_parent" android:layout_height="26dip" android:layout_toRightOf="@id/icon" android:layout_alignParentBottom="true" android:layout_alignParentRight="true"

ANDROID, uma viso geral Anderson Duarte de Amorim

231

android:singleLine="true" android:ellipsize="marquee" android:text="Simple application that shows how to use RelativeLayout" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toRightOf="@id/icon" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_above="@id/secondLine" android:layout_alignWithParentIfMissing="true" android:gravity="center_vertical" android:text="My Application" /> </RelativeLayout>

Esta nova aplicao se comporta exatamente da mesma forma que a implementao anterior, exceto em um caso: o item da lista que se pretende apresentar tem duas linhas de texto: o ttulo e uma descrio opcional. Quando uma descrio no est disponvel para um determinado item da lista o aplicativo simplesmente define a visibilidade do segundo TextView como GONE. Isso funciona perfeitamente com o LinearLayout, mas no com o RelativeLayout:

Em um RelativeLayout, as vistas so alinhadas com a sua me, com o


RelativeLayout

em si, ou com outras vises. Por exemplo, ns declaramos que a

descrio est alinhado com a parte inferior da RelativeLayout e que o ttulo colocado acima da descrio e ancorado a me da top. Com a descrio GONE, o RelativeLayout no sabe a posio da margem inferior do ttulo. Para resolver esse problema, voc pode usar um parmetro muito especial chamado

layout_alignWithParentIfMissing. Este parmetro boolean simplesmente diz ao RelativeLayout a utilizar os seus prprios limites como ncoras quando um alvo est faltando. Por exemplo, se voc posicionar uma view direita de uma GONE e definir alignWithParentIfMissing como true,

ANDROID, uma viso geral Anderson Duarte de Amorim

232

RelativeLayout

vez vai ancorar o fim de sua borda esquerda. No nosso caso, usando far RelativeLayout alinhar a parte inferior do ttulo

alignWithParentIfMissing

com si mesmo. O resultado o seguinte:

O comportamento do nosso layout est perfeito, mesmo quando a descrio GONE. Ainda melhor, a hierarquia mais simples porque no estamos usando pesos LinearLayout's tambm mais eficiente. A diferena entre as duas implementaes torna-se evidente quando se comparam as hierarquias em HierarchyViewer:

ANDROID, uma viso geral Anderson Duarte de Amorim

233

Truques de layout: usando ViewStub


Compartilhamento e reutilizao de componentes de interface do usurio so muito fceis com o Android, graas tag <include/>. s vezes to fcil criar complexas construes UI que UI termina com um grande nmero de pontos de vista, algumas das quais raramente so utilizados. Felizmente, o Android oferece um widget muito especial chamado ViewStub , que traz todos os benefcios da <include /> sem poluir a interface do usurio com views raramente utilizadas. A ViewStub uma viso leve. No tem dimenso, no tira nada e no participa no layout de qualquer forma. Isso significa que uma ViewStub muito barata para inflar e muito barata para se manter em uma hierarquia de vista. A ViewStub pode ser melhor descrita como um preguioso <include />. O esquema referenciado por um ViewStub inflado e adicionado interface do usurio somente quando assim o decidir. A figura a seguir vem da aplicao Prateleira. O principal objetivo da atividade

mostrado na imagem apresentar ao usurio uma lista pesquisvel dos livros:

ANDROID, uma viso geral Anderson Duarte de Amorim

234

A atividade tambm usada quando o usurio adiciona ou importa novos livros. Durante essa operao, a Prateleira mostra bits adicionais de interface do usurio. A imagem abaixo mostra a barra de progresso e um boto cancelar que aparecer na parte inferior da tela durante uma importao:

Como a importao de livros no uma operao comum, pelo menos quando comparado visita a lista de livros, o painel de importao representado inicialmente por um ViewStub :

ANDROID, uma viso geral Anderson Duarte de Amorim

235

Quando o usurio inicia o processo de importao, o ViewStub inflado e passa a ter o contedo do arquivo de layout que faz referncia:

ANDROID, uma viso geral Anderson Duarte de Amorim

236

Para usar um ViewStub , tudo que voc precisa especificar um atributo android:id, para depois inflar, e um atributo android:layout para fazer referncia ao arquivo de layout para incluir e inflar. Um stub permite que voc use um terceiro atributo, android:inflatedId , que pode ser usado para substituir o id da raiz do arquivo includo. Finalmente, os parmetros de layout especificados no topo sero aplicados para a raiz do layout includo. Aqui est um exemplo:
<ViewStub android:id="@+id/stub_import" android:inflatedId="@+id/panel_import" android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" />

Quando estiver pronto para inflar o stub, basta invocar o mtodo inflate(). Voc tambm pode simplesmente alterar a visibilidade do stub para VISIBLE ou INVISIBLE e o stub ir inflar. Note, no entanto que o mtodo inflate() tem a vantagem de retornar a raiz View ao inflar o layout:
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE); // or View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();

muito importante lembrar que aps o stub ser inflado, o topo removido da hierarquia de vista. Como tal, necessrio manter uma referncia de vida longa, por exemplo, em um campo de instncia de classe, a uma ViewStub . Um ViewStub um grande compromisso entre a facilidade de programao e de eficincia. Em vez de encher vistas manualmente e adicion-los em tempo de execuo de sua hierarquia de vista, basta usar um ViewStub. barato e fcil. A nica desvantagem de ViewStub que atualmente no suporta a tag <merge />.

Truques de layout: mesclando layouts


A tag <merge /> foi criada com a finalidade de otimizar layouts Android, reduzindo o nmero de nveis em rvores de vista. mais fcil entender o problema que esta tag resolve olhando um exemplo. O esquema XML a seguir declara um layout que mostra uma imagem com o ttulo em cima dela. A estrutura bastante simples, uma

FrameLayout usada para empilhar um TextView em cima de um ImageView : ANDROID, uma viso geral Anderson Duarte de Amorim

237

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip" android:layout_gravity="center_horizontal|bottom" android:padding="12dip" android:background="#AA000000" android:textColor="#ffffffff" android:text="Golden Gate" /> </FrameLayout>

Isso torna o layout bem e nada parece errado com ele:

ANDROID, uma viso geral Anderson Duarte de Amorim

238

As coisas ficam mais interessantes quando voc inspecionar o resultado com HierarchyViewer. Se voc olhar atentamente para a rvore resultante, voc vai notar que o FrameLayout definida no arquivo XML (destacada em azul abaixo) o filho nico de outro FrameLayout:

S fizemos a interface mais complexa, sem qualquer razo. Mas como poderamos nos livrar do presente FrameLayout? Afinal de contas, documentos XML requerem uma marca de raiz e tags em esquemas XML sempre representam instncias. a que o <merge /> vem a calhar. Quando o LayoutInflater encontra essa marca, ele ignora-o e adiciona o <merge /> dos nodos ao <merge /> pai. Confuso? Vamos reescrever o nosso layout XML anterior, substituindo o FrameLayout com <merge />: ANDROID, uma viso geral Anderson Duarte de Amorim

239

<merge xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip" android:layout_gravity="center_horizontal|bottom" android:padding="12dip" android:background="#AA000000" android:textColor="#ffffffff" android:text="Golden Gate" /> </merge>

Com esta nova verso, tanto o TextView quanto o ImageView sero adicionados diretamente ao nvel superior. O resultado ser o mesmo, mas visualmente a hierarquia do ponto de vista simples:

ANDROID, uma viso geral Anderson Duarte de Amorim

240

Obviamente, o uso do <merge /> funciona neste caso porque o nodo pai sempre um FrameLayout. Voc no pode aplicar este truque se o layout estava usando um LinearLayout como sua marca raiz, por exemplo. O <merge /> pode ser til em outras situaes, no entanto. Por exemplo, ele funciona perfeitamente quando combinado com o <include />. Voc tambm pode usar <merge /> quando voc cria um composto de exibio personalizado. Vamos ver como podemos usar essa tag para criar uma nova viso chamada OkCancelBar que simplesmente mostra dois botes com rtulos personalizados.
<merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <com.example.android.merge.OkCancelBar android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:paddingTop="8dip" android:gravity="center_horizontal" android:background="#AA000000" okCancelBar:okLabel="Save" okCancelBar:cancelLabel="Don't save" /> </merge>

ANDROID, uma viso geral Anderson Duarte de Amorim

241

O cdigo fonte do OkCancelBar muito simples, porque os dois botes so definidos em um arquivo XML externo, carregado com um LayoutInflate. Como voc pode ver no trecho a seguir, o esquema XML R.layout.okcancelbar inflado com o OkCancelBar como o pai:
public class OkCancelBar extends LinearLayout { public OkCancelBar(Context context, AttributeSet attrs) { super(context, attrs); setOrientation(HORIZONTAL); setGravity(Gravity.CENTER); setWeightSum(1.0f); LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0); String text = array.getString(R.styleable.OkCancelBar_okLabel); if (text == null) text = "Ok"; ((Button) findViewById(R.id.okcancelbar_ok)).setText(text); text = array.getString(R.styleable.OkCancelBar_cancelLabel); if (text == null) text = "Cancel"; ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);

ANDROID, uma viso geral Anderson Duarte de Amorim

242

array.recycle(); } }

Os dois botes so definidos no esquema XML a seguir. Como voc pode ver, usamos o <merge /> para adicionar os dois botes diretamente ao OkCancelBar . Cada boto est includo a partir do arquivo XML externo mesmo layout para torn-los mais fceis de manter, ns simplesmente substituimos o seu id:
<merge xmlns:android="http://schemas.android.com/apk/res/android"> <include layout="@layout/okcancelbar_button" android:id="@+id/okcancelbar_ok" /> <include layout="@layout/okcancelbar_button" android:id="@+id/okcancelbar_cancel" /> </merge>

Ns criamos uma forma flexvel e fcil de manter a exibio personalizada que gera uma hierarquia de vista eficiente:

ANDROID, uma viso geral Anderson Duarte de Amorim

243

O <merge /> extremamente til e pode fazer maravilhas em seu cdigo. No entanto, ele sofre de um par de limitaes: <merge /> s pode ser usado como a tag raiz de um esquema XML Ao inflar um layout comeando com uma <merge /> voc deve especificar um pai ViewGroup e voc deve definir attachToRoot como true

ListView, uma otimizao


ListView um dos widgets mais amplamente utilizados no Android. bastante fcil de usar, muito flexvel e incrivelmente poderoso. Um dos problemas mais comuns com ListView acontece quando voc tenta usar um plano personalizado. Por padro, como muitos widgets do Android, o ListView tem um fundo transparente, o que significa que voc pode ver atravs do padro da janela do fundo. Alm disso, ListView permite as margens de desvanecimento por padro, como voc pode ver no topo da tela a seguir - o texto do primeiro item desvanece-se gradualmente para preto. Esta tcnica utilizada em todo o sistema para indicar que o continer pode ser rolado.

ANDROID, uma viso geral Anderson Duarte de Amorim

244

O efeito de fade implementado usando uma combinao de Canvas.saveLayerAlpha() e Porter-Duff Destination Out blending mode. Infelizmente, as coisas comeam a ficarem feias quando voc tenta usar um background personalizado no ListView ou quando voc muda a janela de fundo. A seguir duas imagens mostram o que acontece em um aplicativo quando voc mudar o fundo da janela. A imagem da esquerda mostra como a lista se parece por padro e a imagem da direita mostra o como a lista se parece durante um deslocamento iniciado com um gesto de tocar:

Este problema de processamento causada por uma otimizao do quadro Android ativada por padro em todas as instncias do ListView. Esta aplicao funciona muito bem, mas infelizmente muito caro e pode trazer para baixo o desempenho de desenho, um pouco como ele necessita para capturar uma parcela da prestao em um bitmap fora da tela e, em seguida, requer a mistura extra (o que implica readbacks da memria). ListViews so, na maioria das vezes exibidos em uma base slida, no h nenhuma razo para enveredar por esse caminho caro. por isso que ns introduzimos uma otimizao chamada de pitada de cor cache. A dica de cor cache uma cor RGB definido por padro com a cor de fundo da janela, que #191919 no tema escuro do

ANDROID, uma viso geral Anderson Duarte de Amorim

245

Android. Quando esta dica definida, ListView (na verdade, sua classe base View) sabe que vai recorrer a um fundo slido e substitui, portanto, a cara renderizao saveLayerAlpha()/Porter-Duff por um gradiente simples. Este gradiente vai desde totalmente transparente para o valor de cor cache e exatamente isso que voc v na imagem acima, com o gradiente escuro na parte inferior da lista. No entanto, isso ainda no explica por que a lista inteira fica em preto durante um pergaminho. Como mencionado anteriormente, ListView tem um fundo transparente/translcido por padro, assim como todos os widgets padro na caixa de ferramentas UI Android. Isto implica que, quando ListView redesenha seus filhos, tem que misturar as crianas com janela de fundo. Mais uma vez, isto requer readbacks caros de memria que so particularmente dolorosos durante um deslocamento ou uma aventura, quando acontece o desenho dezenas de vezes por segundo. Para melhorar o desempenho de desenho durante as operaes de rolagem, o quadro Android reutiliza a dica de cor cache. Para corrigir esse problema, tudo que voc tem que fazer desativar o cache de otimizao de cor, se voc usar uma cor de fundo no-contnua, ou definir a dica para o valor de cor slido adequado. Voc pode fazer isso a partir do cdigo ou, de preferncia, a partir de XML, usando o android:cacheColorHint. Para desabilitar a otimizao, basta usar a cor transparente #00000000. A figura abaixo mostra uma lista com android:cacheColorHint="#00000000" definido no arquivo de layout XML:

ANDROID, uma viso geral Anderson Duarte de Amorim

246

Como voc pode ver, o fade funciona perfeitamente contra o fundo personalizado em madeira. O recurso de cache de sugesto de cor interessante porque mostra como as otimizaes podem tornar sua vida mais difcil em algumas situaes. Neste caso especfico, porm, o benefcio do comportamento padro compensa a maior complexidade.

Live folders
Live Folders, introduzida no Android 1.5 API (Nvel 3), permitem a exibio de qualquer fonte de dados na tela inicial, sem forar o usurio a lanar uma aplicao. Uma live folder simplesmente uma viso em tempo real de um ContentProvider. Como tal, uma live folder pode ser usada para exibir todos os contatos do usurio ou bookmarks, e-mail, listas de reproduo, um feed RSS, e assim por diante. possibilidades so infinitas! A plataforma inclui vrias pastas padro para a exibio de contatos. Por exemplo, a imagem abaixo mostra o contedo das pastas ao vivo que mostra todos os contatos com um nmero de telefone: As

ANDROID, uma viso geral Anderson Duarte de Amorim

247

Se a sincronizao de contatos acontece em segundo plano enquanto o usurio est visitando esta pasta ao vivo, o usurio ver a mudana acontecer em tempo real. Live folders no so apenas teis, mas elas tambm so fceis de adicionar ao seu aplicativo. Este artigo mostra como adicionar uma live folder para uma aplicao, como por exemplo as chamadas Prateleiras. Para entender melhor como trabalham as pastas, voc pode baixar o cdigo fonte da aplicao e modific-lo seguindo as instrues abaixo. Para dar ao usurio a opo de criar uma nova pasta para um aplicativo, voc primeiro precisa criar uma nova atividade com a inteno de filtro cuja ao android.intent.action.CREATE_LIVE_FOLDER. Para isso, basta abrir

AndroidManifest.xml e adicionar algo semelhante a isto:


<activity android:name=".activity.BookShelfLiveFolder" android:label="BookShelf"> <intent-filter> <action android:name="android.intent.action.CREATE_LIVE_FOLDER" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>

O rtulo e o cone desta atividade so o que o usurio ver na tela inicial quando se escolhe uma pasta:

ANDROID, uma viso geral Anderson Duarte de Amorim

248

Uma vez que voc s precisa de uma inteno de filtro, possvel e, por vezes aconselhvel, a reutilizao de uma atividade existente. No caso de Prateleiras, vamos criar uma nova O atividade, papel desta

org.curiouscreature.android.shelves.activity.BookShelfLiveFolder.

atividade enviar um resultado Intent para Pgina contendo a descrio da live folder: o seu nome, cone, modo de apresentao e contedo URI. O URI contedo muito importante, pois descreve o que ContentProvider ser usado para preencher a live folder. O cdigo da atividade muito simples, como voc pode ver aqui:
public class BookShelfLiveFolder extends Activity { public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Intent intent = getIntent(); final String action = intent.getAction(); if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) { setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI, "Books", R.drawable.ic_live_folder)); } else { setResult(RESULT_CANCELED); } finish(); } private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) { final Intent intent = new Intent(); intent.setData(uri); intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name); intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON, Intent.ShortcutIconResource.fromContext(context, icon)); intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST); return intent; } }

Esta atividade, quando invocada com a ACTION_CREATE_LIVE_FOLDER, retorna com a inteno de um URI, content://shelves/live_folders/books , e trs extras para descrever a pasta ao vivo. Existem outros extras e constantes que voc pode usar e voc deve consultar a documentao do android.provider.LiveFolders para mais detalhes.

ANDROID, uma viso geral Anderson Duarte de Amorim

249

Quando a Home recebe esta ao, uma nova live folder criada no desktop do usurio, com o nome e o cone que voc forneceu. Ento, quando o usurio clica na pasta para abri-la ao vivo, a Home consulta o provedor de contedo referenciado pelo URI fornecido. Prestadores de pastas Live devem obedecer a regras especficas de nomeao. O Cursor retornado pelo mtodo query() deve ter pelo menos duas colunas chamadas LiveFolders._ID e LiveFolders.NAME . O primeiro o identificador nico de cada item na live folder e o segundo o nome do item. H nomes de coluna que voc pode usar para especificar um cone, uma descrio, a inteno de associar ao item (acionado quando o usurio clicar nesse item), etc. Novamente, consulte a documentao do android.provider.LiveFolders para mais detalhes . No nosso exemplo, tudo o que precisamos fazer modificar o provedor existente nas prateleiras Primeiro, chamado precisamos org.curiouscreature.android.shelves.provider.BooksProvider. modificar o URI_MATCHER para reconhecer nosso

content://shelves/live_folders/books URI de contedo:


private static final int LIVE_FOLDER_BOOKS = 4; // ... URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);

Ento, precisamos criar um mapa de nova projeo para o cursor.

Um mapa de

projeo pode ser usado para "renomear" colunas. No nosso caso, vamos substituir BooksStore.Book._ID , BooksStore.Book.TITLE e BooksStore.Book.AUTHORS com LiveFolders._ID , LiveFolders.TITLE e LiveFolders.DESCRIPTION:
private static final HashMap<string, string=""> LIVE_FOLDER_PROJECTION_MAP; static { LIVE_FOLDER_PROJECTION_MAP = new HashMap<string, string="">(); LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID + " AS " + LiveFolders._ID); LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE + " AS " + LiveFolders.NAME); LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS + " AS " + LiveFolders.DESCRIPTION); }

Porque estamos a dar um ttulo e uma descrio para cada linha, Home ir exibir automaticamente cada item da live folder com duas linhas de texto. Finalmente, vamos

ANDROID, uma viso geral Anderson Duarte de Amorim

250

implementar a query(), fornecendo o nosso mapa de projeo para o construtor de consultas SQL:
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); switch (URI_MATCHER.match(uri)) { // ... case LIVE_FOLDER_BOOKS: qb.setTables("books"); qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER); c.setNotificationUri(getContext().getContentResolver(), uri); return c; }

Agora voc pode compilar e implantar o aplicativo, v para a tela inicial e tente adicionar uma live folder. Voc pode adicionar uma pasta para os livros na sua tela inicial e quando voc abri-lo, veja a lista de todos os seus livros, com seus ttulos e autores, e bastou algumas linhas de cdigo:

ANDROID, uma viso geral Anderson Duarte de Amorim

251

A API de live folders extremamente simples e depende apenas de intenes e URI. Se voc quiser ver mais exemplos de aplicao das pastas, voc pode ler o cdigo-fonte do aplicativo de contatos e do provedor de Contatos.

Live Wallpapers
Comeando com o Android 2.1 (API Nvel 7), os utilizadores podem agora desfrutar de papis de parede ao vivo - mais ricos, animados, cenrios interativos - em suas telas iniciais. Um papel de parede ao vivo muito semelhante a uma aplicao Android normal e tem acesso a todas as facilidades da plataforma: SGL (desenho 2D), OpenGL (desenho 3D), GPS, acelermetro, acesso rede, etc. Os papis de parede ao vivo, includo no Nexus One, demonstram o uso de algumas dessas APIs para criar experincias divertidas e interessantes. Por exemplo, o papel de parede da grama usa a localizao do telefone para calcular o nascer e o por do sol, a fim de exibir o cu adequado.

Criar o seu prprio papel de parede ao vivo fcil, especialmente se voc teve experincia anterior com SurfaceView ou Canvas. Para saber como criar um papel de parede ao vivo, voc deve verificar se o cdigo de exemplo CubeLiveWallpaper . Em termos de execuo, um papel de parede ao vivo muito similar a um Service. A nica diferena a adio de um novo mtodo, onCreateEngine(), cujo objetivo criar um WallpaperService.Engine. O dispositivo responsvel pela gesto do ciclo de vida e desenho de um papel de parede. O sistema fornece uma superfcie sobre a qual voc pode desenhar, assim como voc faria com um SurfaceView. Desenho de um papel de parede pode ser muito caro por isso voc deve otimizar o cdigo, tanto quanto possvel para evitar o uso excessivo de CPU, no s para a vida da bateria, mas tambm para evitar a abrandar o resto do sistema. tambm por isso que a parte mais importante do ciclo de vida de um papel de parede quando se torna visvel, como indicado por uma ANDROID, uma viso geral Anderson Duarte de Amorim

252

chamada para onVisibilityChanged(). Quando invisveis, como quando o usurio inicia um aplicativo que cobre a tela inicial, o papel de parede tem que parar todas as atividades. O dispositivo tambm pode implementar vrios mtodos para interagir com o usurio ou o aplicativo de origem. Por exemplo, para reagir ao toque, basta implementar onTouchEvent(). Finalmente, os aplicativos podem enviar comandos arbitrrios para o papel de parede ao vivo. Atualmente, apenas o pedido inicial padro envia comandos para o onCommand() do papel de parede ao vivo:
1.

android.wallpaper.tap: Quando o usurio bate um espao vazio na rea de trabalho. Este comando interpretado pelo dispositivo para fazer o papel de parede reagir interao do usurio.

2.

android.home.drop: Quando o usurio solta um cone ou um widget no espao de trabalho.

Se voc est desenvolvendo um papel de parede ao vivo, lembre-se que o recurso s suportado no Android 2.1 (API nvel 7) e verses superiores da plataforma. Para garantir que seu pedido s pode ser instalado em dispositivos que suportam wallpapers, lembre-se de acrescentar o seguinte trecho de cdigo antes de publicar no Android Market: <uses-sdk android:minSdkVersion="7" />, que indica Android Market e plataforma que seu aplicativo requer Android 2.1 ou superior. <uses-feature android:name="android.software.live_wallpaper" />, que informa Android Market que seu aplicativo inclui um papel de parede ao vivo. Android Market usa esse recurso como um filtro, ao apresentar listas de usurios de aplicaes disponveis. Quando voc declarar esse recurso, o Android Market exibe sua aplicao apenas aos usurios cujas dispositivos suportam wallpapers ao vivo, enquanto oculta de outros dispositivos sobre os quais no seria capaz de executar.

ANDROID, uma viso geral Anderson Duarte de Amorim

253

Usando webViews
Um pequeno aplicativo chamado WebViewDemo mostra como voc pode adicionar contedo da Web em seu aplicativo. Voc pode encontr-la no projeto de aplicativos para Android. Esta aplicao demonstra como voc pode incorporar um WebView em uma atividade e tambm como voc pode ter comunicao bidirecional entre o aplicativo e o contedo da web. Um WebView utiliza o mesmo processamento e motor de JavaScript, o navegador, mas ele executado sob o controle de sua aplicao. O WebView podem ser em tela cheia ou voc pode mistur-la com outras vises. O WebView pode baixar contedo da web, ou pode vir a partir de arquivos locais armazenados em seu diretrio de ativos. O contedo pode at ser gerado dinamicamente pelo cdigo do aplicativo. Este aplicativo no faz muita coisa: quando voc clica sobre o Android, ele levanta o brao.

Isso poderia, naturalmente, ser facilmente conseguido com um pouco de JavaScript. Em vez disso, porm, WebViewDemo toma um caminho um pouco mais complicado para ilustrar duas caractersticas muito poderosa de WebView. Primeiro, o JavaScript em execuo dentro do WebView pode se ligar com o cdigo em sua atividade. Voc pode usar isso para fazer suas aes disparar JavaScript como comear uma nova atividade, ou pode ser usada para buscar dados de um banco de dados ou ContentProvider . A API para isso muito simples: basta conectar com o addJavascriptInterface()em sua WebView. Voc passa um objeto cujos mtodos voc

ANDROID, uma viso geral Anderson Duarte de Amorim

254

deseja expor ao JavaScript e o nome a ser usado para fazer chamadas. Voc pode ver a sintaxe exata em WebViewDemo.java. Aqui ns estamos fazendo o nosso objeto DemoJavascriptInterface disponvel em JavaScript para onde ele vai ser chamado de "window.demo". Em segundo lugar, sua atividade pode invocar mtodos JavaScript. Tudo que voc tem a fazer chamar o mtodo loadUrl com a chamada de JavaScript apropriada:
mWebView.loadUrl("javascript:wave()");

Nosso WebViewDemo utiliza duas tcnicas: quando voc clica sobre o Android, que chama a atividade, que ento se vira e chama de volta para o JavaScript. WebViews so muito poderosos e podem ser uma ferramenta valiosa para ajudar a construir a sua aplicao - especialmente se voc j tem um monte de contedo HTML. Quando isso acontece, usamos exatamente essa abordagem em algumas das aplicaes que ns escrevemos.

Funcionalidades
Caixa de pesquisa
Comeando com o Android 1.6, a plataforma inclui suporte para caixa de pesquisa rpida (CPR ou QSB Quick Search Box), uma poderosa estrutura de pesquisa de todo o sistema. A caixa de pesquisa rpida permite que os usurios rapidamente e facilmente encontrem o que procuram, tanto em seus dispositivos quanto na web. Ele sugere contedo no seu dispositivo enquanto voc digita como aplicativos, contatos, histrico do navegador, e msica. Tambm oferece resultados das sugestes de pesquisa na web, anncios de empresas locais e outras informaes do Google, tais como cotaes da bolsa, previso do tempo e status de vo. Tudo isso est disponvel logo na tela inicial, tocando na caixa de pesquisa rpida. Seus aplicativos podem fornecer sugestes de pesquisa que surgiro a usurios de CPR junto com outros resultados de pesquisa e sugestes. Isso torna possvel para os usurios acessem o contedo do seu aplicativo de fora da sua aplicao, por exemplo, a partir da tela inicial.

ANDROID, uma viso geral Anderson Duarte de Amorim

255

Nota: Os fragmentos de cdigo deste documento esto relacionados a um aplicativo de exemplo chamado Dicionrio pesquisvel. O aplicativo est disponvel para o Android 1.6 e plataformas posteriores. Plataforma de lanamentos de verses anteriores para o Android 1.6 j previam um mecanismo que permite que voc exponha pesquisa e sugestes de busca na sua aplicao, conforme descrito na documentao para SearchManager. Esse mecanismo no mudou e exige as seguintes coisas em sua AndroidManifest.xml :
1.

Em sua <activity>, a inteno do filtro, e uma referncia a um searchable.xml arquivo (descritas abaixo):
<intent-filter> <action android:name="android.intent.action.SEARCH" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />

2.

Um provedor de contedo que pode oferecer sugestes de pesquisa de acordo com as URIs e formatos de coluna especificada pelo Sugestes de Pesquisa seo do docs SearchManager.
<!-- Provides search suggestions for words and their definitions. --> <provider android:name="DictionaryProvider" android:authorities="dictionary" android:syncable="false" />

No searchable.xml, voc especifica algumas coisas sobre como voc deseja que o sistema de busca apresente a pesquisa para a sua aplicao, incluindo a autoridade do provedor de contedo que oferece sugestes para o usurio enquanto digitam. Aqui est um exemplo do searchable.xml de um aplicativo do Android que fornece sugestes de pesquisa dentro de suas prprias atividades:
<searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/search_label" android:searchSuggestAuthority="dictionary" android:searchSuggestIntentAction="android.intent.action.VIEW"> </searchable>

ANDROID, uma viso geral Anderson Duarte de Amorim

256

No Android 1.6, que adicionou um novo atributo para os metadados conhecido como: android:includeInGlobalSearch. Especificando-a como "true" no seu searchable.xml, voc permite que QSB a pegar sua pesquisa provedor de contedo e d sugesto de incluso (se o usurio permite que suas sugestes a partir das definies de pesquisa do sistema). Voc tambm deve especificar um valor de cadeia para

android:searchSettingsDescription, que descreve aos usurios que tipo de sugestes o seu aplicativo fornece nas configuraes do sistema para a pesquisa.
<searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/search_label" android:searchSettingsDescription="@string/settings_description" android:includeInGlobalSearch="true" android:searchSuggestAuthority="dictionary" android:searchSuggestIntentAction="android.intent.action.VIEW"> </searchable>

O mais importante e primeira coisa a notar que quando um usurio instala um aplicativo com um provedor de sugesto que participam no CPR, esta nova aplicao no ser ativado por padro para o CPR. O usurio pode optar por ativar as fontes de sugesto especial, as configuraes do sistema para a pesquisa (clicando em "Pesquisar" > "itens pesquisveis" nas configuraes). Voc deve pensar em como lidar com isso em sua aplicao. Talvez mostrar um aviso de que instrui o usurio a visitar as configuraes do sistema e permitir as sugestes do seu aplicativo. Quando o usurio habilita o item pesquisado, sugestes do aplicativo tero a chance de aparecer na QSB. Como sugestes de sua aplicao so escolhidas com mais freqncia, eles podem se mover para cima na lista.

ANDROID, uma viso geral Anderson Duarte de Amorim

257

Um dos nossos objetivos com o CPR torn-lo mais rpido para que os usurios acessem as coisas com mais freqncia. Uma maneira que fizemos isso 'shortcutting' algumas das sugestes de pesquisa previamente escolhido, ento eles sero mostrados imediatamente quando o usurio comea a digitar, ao invs de esperar para consultar os fornecedores de contedos. Sugestes de sua aplicao podem ser escolhidas como atalhos quando o usurio clica neles. Para sugestes de dinmicas que podem querer alterar o seu contedo (ou se tornar invlido), no futuro, voc pode fornecer um 'id atalho.

Sistema
Alocao de memria
Escrever eficazes aplicaes mveis nem sempre fcil. Em particular, aplicaes Android dependem de gerenciamento automtico de memria manipulado pelo coletor de lixo Dalvik, que por vezes pode causar problemas de desempenho se voc no for cuidadoso com as alocaes de memria. Em um caminho de cdigo de desempenho sensveis, tais como o mtodo de layout ou desenho de uma vista ou o cdigo da lgica de um jogo, qualquer atribuio tem um preo. Depois de muitas atribuies, o coletor de lixo vai comear e parar o aplicativo para deix-lo liberar memria. Na maioria das vezes, as coletas de lixo acontecem rpidas o suficiente para voc no perceber. No entanto, se uma coleo acontece enquanto voc estiver percorrendo uma lista de itens ou enquanto voc est tentando

ANDROID, uma viso geral Anderson Duarte de Amorim

258

derrotar um inimigo em um jogo, voc pode de repente ver uma queda no desempenho/ capacidade de resposta do aplicativo. No incomum para uma coleta de lixo levar de 100 a 200 ms. Para comparao, uma animao suave precisa desenhar cada quadro em 16 a 33 ms. Se a animao subitamente interrompida por 10 quadros, voc pode estar certo que os usurios iro notar. Na maioria das vezes, a coleta de lixo ocorre por causa de toneladas de objetos pequenos, de curta durao e alguns coletores de lixo, como catadores de lixo de geraes, que podem otimizar a coleta desses objetos para que o aplicativo no se interrompa com muita freqncia. O coletor de lixo Android infelizmente no capaz de realizar tais otimizaes e na criao de objetos de curta durao em caminhos de cdigo crtico de desempenho , portanto, muito caro para sua aplicao. Para ajudar a evitar freqentes coletas de lixo, o SDK do Android embarcado com uma ferramenta muito til chamado allocation tracker. Esta ferramenta parte do DDMS, que voc j deve ter usado para fins de depurao. Para comear a usar o tracker de atribuio, primeiro voc deve lanar a verso autnoma do DDMS, que pode ser encontrado na tools/ do SDK. A verso do DDMS includo no Eclipse plugin no oferece capacidade de usar o tracker de atribuio ainda. Depois DDMS estar funcionando, basta selecionar o seu processo de candidatura e, em seguida, clique na guia Atribuio Tracker. Na nova viso, clique em Iniciar monitoramento e ento usar o aplicativo para torn-lo executvel para os caminhos de cdigo que voc deseja analisar. Quando estiver pronto, clique em Obter atribuies. Uma lista de objetos alocados ser mostrada no primeiro quadro. Ao clicar em uma linha voc pode ver, na segunda tabela, o rastreamento de pilha que levaram atribuio. No somente voc saber que tipo de objeto foi alocado, mas tambm em qual segmento, em que classe, em qual arquivo e em qual linha. A figura abaixo mostra as atribuies realizadas por prateleiras enquanto estiver rolando um ListView.

ANDROID, uma viso geral Anderson Duarte de Amorim

259

O tracker de atribuio ajudar voc a identificar questes importantes em seu cdigo. Por exemplo, um erro comum que tenho visto em muitas aplicaes a criao de uma novo objeto Paint em cada sorteio. Mover a pintura em um campo de instncia uma soluo simples que ajuda no desempenho de um lote. Eu altamente encorajo-vos a examinar o cdigo fonte do Android para ver como podemos reduzir dotaes em caminhos de cdigo crtico de desempenho. Voc tambm vai descobrir o Android, assim, oferecer APIs para ajudar voc a reutilizar objetos.

Zipaling oferece uma otimizao fcil


O Android SDK inclui uma ferramenta chamada zipalign que otimiza a forma como um aplicativo empacotado. Rodando Zipalign em seu aplicativo permite que o Android possa interagir de forma mais eficiente em tempo de execuo e, portanto, tem o potencial para faz-lo executar o sistema global mais rpido. No Android, arquivos de dados armazenados em APK de cada aplicativo so acessados por vrios processos: o instalador l o manifesto para lidar com as permisses associadas com o pedido; a aplicao inicial l recursos para obter o nome do aplicativo

ANDROID, uma viso geral Anderson Duarte de Amorim

260

e um cone; o sistema servidor l os recursos para uma variedade de razes (por exemplo, para exibir as notificaes que aplicativo), e por ltimo mas no menos importante, os arquivos de recurso so, obviamente, utilizado pelo prprio aplicativo. Os cdigos de manipulao de recursos no Android podem acessar os recursos de forma eficiente quando esto alinhados em limites de 4 bytes de memria. Mas, para recursos que no esto alinhados (ou seja, quando zipalign no tenha sido executado em um APK), ele tem que cair de volta a expressamente e l-los - o que mais lento e consome memria adicional. Para um desenvolvedor de aplicativos, este mecanismo de retorno muito conveniente. Ele oferece uma grande flexibilidade, permitindo o desenvolvimento de vrios mtodos diferentes, incluindo aqueles que no incluem a agregao de recursos como parte de seu fluxo normal. Infelizmente, para os usurios a situao inversa - os recursos de leitura de APKs desalinhados so lentos e exigem muito da memria. No melhor dos casos, o nico resultado visvel que tanto a aplicao inicial quanto o lanamento de aplicaes desalinhadas so mais lentos do que deveria. No pior dos casos, a instalao de vrias aplicaes com recursos de memria no alinhadas aumentam a presso, causando assim problemas para o sistema por ter que constantemente iniciar e matar processos. O usurio acaba com um dispositivo lento, com uma durao de bateria fraca. Felizmente, muito fcil para o alinhar recursos em sua aplicao: Usando ADT:
o

A ADT, plugin para o Eclipse (a partir da verso 0.9.3), alinhar automaticamente os pacotes de aplicativos libertados se a assistente de exportao usado para cri-las.

Usando Ant:
o

O script de construo Ant (a partir do Android 1.6) pode alinhar os pacotes de aplicativos. Metas para verses mais antigas da plataforma Android no so alinhados pelo script de construo Ant e precisam ser manualmente alinhados.

ANDROID, uma viso geral Anderson Duarte de Amorim

261

A partir dos 1,6 Android SDK, Ant alinha pacotes de sinais automaticamente, quando est construindo o modo de depurao.

No modo de lanamento, Ant alinha as embalagens se tiver informao suficiente para assinar os pacotes, uma vez que o alinhamento deve acontecer aps a assinatura. A fim de poder assinar os pacotes, e, portanto, para alinh-los, Ant precisa saber a localizao do armazenamento de chaves e o nome da chave na build.properties. O nome das propriedades so key.store e key.alias. Se as propriedades estiverem ausentes, o pacote de lanamento no ser assinado e, portanto, no vai se alinhar tambm.

Manualmente:
o

A fim de alinhar manualmente um pacote, zipalign est no tools/ do Android SDK 1.6 e posteriores. Voc pode us-lo para alinhar os pacotes de aplicativos voltados para qualquer verso do Android. Voc deve execut-lo somente aps a assinatura do arquivo APK, usando o seguinte comando: zipalign -v 4 source.apk destination.apk

Verificando o alinhamento:
o

comando

seguir

verifica

se

um

pacote

est

alinhado:

zipalign -c -v 4 application.apk

ANDROID, uma viso geral Anderson Duarte de Amorim

262

Nota
Todo o contedo foi retirado de <http://android.com> e correlatos sendo disponibilizado atravs da licena Apache 2.0 e traduzido com auxlio de <http://translate.google.com.br> com posterior reviso.

Fontes
About the Android Open Source Project. Disponvel em: <http://source.android.com/about/index.html>. Acesso em: 06 abril 2011. Activities. Disponvel em: <http://developer.android.com/guide/topics/fundamentals/activities.html>. Acesso em: 22 maro 2011. Application Resources. Disponvel em: <http://developer.android.com/guide/topics/resources/index.html>. Acesso em: 05 abril 2011. Applying Styles and Themes. Disponvel em: <http://developer.android.com/guide/topics/ui/themes.html>. Acesso em: 04 abril 2011. Bound Services. Disponvel em: <http://developer.android.com/guide/topics/fundamentals/bound-services.html>. Acesso em: 25 maro 2011. Creating Dialogs. Disponvel em: <http://developer.android.com/guide/topics/ui/dialogs.html>. Acesso em: 01 abril 2011. Creating Menus. Disponvel em: <http://developer.android.com/guide/topics/ui/menus.html>. Acesso em: 30 maro 2011. Creating Status Bar Notifications. Disponvel em: <http://developer.android.com/guide/topics/ui/notifiers/notifications.html>. Acesso em: 04 abril 2011.

ANDROID, uma viso geral Anderson Duarte de Amorim

263

Creating Toast Notifications. Disponvel em: <http://developer.android.com/guide/topics/ui/notifiers/toasts.html>. Acesso em: 04 abril 2011. Data Backup. Disponvel em: <http://developer.android.com/guide/topics/data/backup.html>. Acesso em: 06 abril 2011. Data Storage. Disponvel em: <http://developer.android.com/guide/topics/data/data-storage.html>. Acesso em: 05 abril 2011. Declaring Layout. Disponvel em: <http://developer.android.com/guide/topics/ui/declaring-layout.html>. Acesso em: 29 maro 2011. Fragments. Disponvel em: <http://developer.android.com/guide/topics/fundamentals/fragments.html>. Acesso em: 22 maro 2011. Handling UI Events. Disponvel em: <http://developer.android.com/guide/topics/ui/ui-events.html>. Acesso em: 04 abril 2011. How Android Draws Views. Disponvel em: <http://developer.android.com/guide/topics/ui/how-android-draws.html>. Acesso em: 04 abril 2011. Loaders. Disponvel em: <http://developer.android.com/guide/topics/fundamentals/loaders.html>. Acesso em: 23 maro 2011. Notifying the User. Disponvel em: <http://developer.android.com/guide/topics/ui/notifiers/index.html>. Acesso em: 04 abril 2011. Processes and Threads. Disponvel em:

ANDROID, uma viso geral Anderson Duarte de Amorim

264

<http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html>. Acesso em: 25 maro 2011.

ANDROID, uma viso geral Anderson Duarte de Amorim

265

Services. Disponvel em: <http://developer.android.com/guide/topics/fundamentals/services.html>. Acesso em: 25 maro 2011. Tasks and Back Stack. Disponvel em: <http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html>. Acesso em: 24 maro 2011. User Interface. Disponvel em: <http://developer.android.com/guide/topics/ui/index.html>. Acesso em: 29 maro 2011. Using the Action Bar. Disponvel em: <http://developer.android.com/guide/topics/ui/actionbar.html>. Acesso em: 30 maro 2011.

Fontes das imagens


Androids. Disponvel em: <http://www.android.com/media/wallpaper/gif/androids.gif>. Acesso em: 06 abril 2011. Untitled. Disponvel em: <http://t3.gstatic.com/images?q=tbn:ANd9GcSknkUiTjwIBqS6dGp8k5IR2ihXI1ipyrols 9PHvLL2nq9GLVd0lg&t=1>. Acesso em: 04 abril 2011.

Fontes dos artigos


Accessibility Service. Disponvel em: <http://developer.android.com/resources/samples/AccessibilityService/index.html>. Acesso em: 18 maro 2011. Drawable Mutations. Disponvel em: <http://developer.android.com/resources/articles/drawable-mutations.html>. Acesso em: 18 maro 2011. Gestures. Disponvel em: <http://developer.android.com/resources/articles/gestures.html>. Acesso em: 18 maro 2011.

ANDROID, uma viso geral Anderson Duarte de Amorim

266

Layout Tricks: Creating Efficient Layouts. Disponvel em: <http://developer.android.com/resources/articles/layout-tricks-efficiency.html>. Acesso em: 21 maro 2011. Layout Tricks: Merging Layouts. Disponvel em: <http://developer.android.com/resources/articles/layout-tricks-merge.html>. Acesso em: 21 maro 2011. Layout Tricks: Using ViewStubs. Disponvel em: <http://developer.android.com/resources/articles/layout-tricks-stubs.html>. Acesso em: 21 maro 2011. Live Folders. Disponvel em: <http http://developer.android.com/resources/articles/live-folders.html>. Acesso em: 21 maro 2011. Live Wallpapers. Disponvel em: <http://developer.android.com/resources/articles/live-wallpapers.html>. Acesso em: 21 maro 2011. ListView Backgrounds: An Optimization. Disponvel em: <http://developer.android.com/resources/articles/listview-backgrounds.html>. em: 21 maro 2011. Touch Mode. Disponvel em: <http://developer.android.com/resources/articles/touch-mode.html>. Acesso em: 21 maro 2011. Using Text-to-Speech. Disponvel em: <http://developer.android.com/resources/articles/tts.html>. Acesso em: 18 maro 2011. Zipalign: an Easy Optimization. Disponvel em: <http://developer.android.com/resources/articles/zipalign.html>. Acesso em: 21 maro 2011. Acesso

ANDROID, uma viso geral Anderson Duarte de Amorim

267