• Nenhum resultado encontrado

Adicionando links externos ao RestaurantFinder

No documento Android em Ação - 3°. Edição (páginas 134-138)

Intents e Services

4.1.3 Adicionando links externos ao RestaurantFinder

Quando começamos o RestaurantFinder na Listagem 3.6, usamos objetos Intent

para nos mover entre as telas do nosso aplicativo. Na listagem seguinte, finalizamos a Activity ReviewDetail usando um novo conjunto de objetos Intent implícitos para conectar o usuário a outros aplicativos do telefone.

lisTagem 4.1 Segunda sessão de ReviewDetail, demonstrando a invocação Intent

@Override

public boolean onMenuItemSelected(int featureId, MenuItem item) { Intent intent = null;

switch (item.getItemId()) { case MENU_WEB_REVIEW:

if ((link != null) && !link.equals("")) { intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link)); startActivity(intent); } else { new AlertDialog.Builder(this) setTitle(getResources() .getString(R.string.alert_label)) .setMessage(R.string.no_link_message) .setPositiveButton("Continue", new OnClickListener() {

public void onClick(DialogInterface dialog, int arg1) { } }).show(); } return true; case MENU_MAP_REVIEW: if ((location.getText() != null) && !location.getText().equals("")) { intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=" + location.getText().toString())); startActivity(intent); } else { new AlertDialog.Builder(this) .setTitle(getResources() .getString(R.string.alert_label)) .setMessage(R.string.no_location_message)

.setPositiveButton("Continue", new OnClickListener() { public void onClick(DialogInterface dialog, int arg1) { } }).show(); } return true; case MENU_CALL_REVIEW: if ((phone.getText() != null) && !phone.getText().equals("") && !phone.getText().equals("NA")) { String phoneString = parsePhone(phone.getText().toString());

q

Declara o Intent

w

Mostra a página web

e

Configura o Intent para o item de menu map

Servindo o RestaurantFinder com Intent 107

intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phoneString)); startActivity(intent); } else { new AlertDialog.Builder(this) .setTitle(getResources() .getString(R.string.alert_label)) .setMessage(R.string.no_phone_message)

.setPositiveButton("Continue", new OnClickListener() { public void onClick(DialogInterface dialog, int arg1) { } }).show(); } return true; }

return super.onMenuItemSelected(featureId, item); }

private String parsePhone(final String phone) { String parsed = phone;

parsed = parsed.replaceAll("\\D", ""); parsed = parsed.replaceAll("\\s", ""); return parsed.trim();

}

O objeto Review contém o endereço e número de telefone de um restaurante e um link para a crítica completa online. Usando a Activity ReviewDetail, o usuário abre o menu e escolhe exibir um mapa com direções para o restaurante, chamar o restaurante ou ver a crítica completa em um navegador web. Para permitir que todas essas ações ocorram, o ReviewDetail executa aplicativos Android nativos por meio de chamadas Intent implícitas.

No nosso novo código, inicializamos uma instância de classe Intent 

q

para que possa ser usada mais tarde nos menus. Se o usuário selecionar o botão de menu

MENU_WEB_REVIEW, criamos uma nova instância da variável Intent inserindo uma ação e dados. Para a ação, usamos a constante String Intent.ACTION_VIEW, que tem o valor android.app.action.VIEW. Você pode usar a constante ou o valor, mas usar constantes ajuda a garantir que você não digite o nome errado. Outras ações comuns são Intent.ACTION_EDIT, Intent.ACTION_INSERT e Intent. ACTION_DELETE.

Para o componente de dados do Intent, usamos Uri.parse(link) para criar um URI. Vamos examinar a Uri em mais detalhes na próxima seção. Por hora, saiba só que isso permite que o componente correto responda a requisição startActiv­ ity (Intent i) 

w

e renderize o recurso identificado pela Uri. Não declaramos diretamente nenhuma Activity ou Service para o Intent. Simplesmente dize- mos o que queremos para a view http://somehost/somepath. O mecanismo de late binding do Android irá interpretar essa requisição durante o tempo de execução, provavelmente iniciando o navegador nativo do dispositivo.

ReviewDetail também manipula o item de menu MENU_MAP_REVIEW. Nós ini- cializamos o Intent para usar Intent.ACTION_VIEW novamente, mas dessa vez com um tipo diferente de URI: "geo:0,0?q=" + street_address 

e

. Essa combinação

w

Configura o Intent para o item de menu call

de VIEW e geo invoca um Intent diferente, prova- velmente o aplicativo de mapas nativo. Finalmente, quando executamos MENU_MAP_CALL, requisitamos uma chamada telefônica usando a ação Intent. ACTION_CALL e o esquema tel:Uri 

r

.

Por meio dessas requisições simples, nosso aplica- tivo RestaurantFinder usa a invocação implícita de

Intent para permitir ao usuário telefonar ou ver o mapa do restaurante selecionado, ou ver a Crítica completa na página web. Esses botões de menu são mostrados na Figura 4.1.

O aplicativo RestaurantFinder agora está com- pleto. Os usuários podem buscar críticas, selecionar uma crítica particular de uma lista, mostrar uma críti- ca detalhada e usar aplicativos nativos adicionais para descobrir mais sobre um restaurante selecionado.

Você aprenderá mais sobre todos os aplicativos nativos e os pares ação-dados na Seção 4.1.5. Agora, vamos nos concentrar no processo de decisão de

Intent e como ele direciona as requisições. 4.1.4 Encontrando seu caminho com Intents

RestaurantFinder faz requisições a outros aplicativos usando invocações de Intents e guia seu movimento interno monitorando requisições de Intent. Três tipos de componentes Android podem se registrar para manipular requisições de Intent:

Activity, Broadcast Receiver e Service. Eles divulgam seus recursos por meio do elemento <intent-filter> no arquivo AndroidManifest.xml.

O Android coloca cada elemento <intent-filter> em um objeto IntentFil­ ter. Depois que o Android instala um arquivo.apk, ele registra os componentes do aplicativo, incluindo os filtros Intent. Quando a plataforma possui um registro de filtros de Intent, ela pode mapear qualquer requisição de Intent para a Activity,

BroadcastReceiver ou Service corretos instalados. Para encontrar o handler apro- priado de um Intent, o Android inspeciona a ação, dados e categorias do Intent. Um <intent-filter> deve atender as seguintes condições para ser considerado:

A ação e categoria devem combinar.

Se especificados, o tipo data também devem combinar, ou a combinação de es-

quema de dados e autoridade e caminho devem combinar. Vamos examinar esses componentes em mais detalhes. AÇÕES E CATEGORIAS

Cada IntentFilter individual pode especificar zero ou mais ações e zero ou mais cate- gorias. Se nenhuma ação for especificada no IntentFilter, ele combinará com qual- quer Intent. Caso contrário, ele combinará somente se o Intent tiver a mesma ação. Um IntentFilter sem categorias combinará somente com um Intent sem catego- rias. Caso contrário, um IntentFilter deve ter no mínimo o que o Intent especifica. Por exemplo, se um IntentFilter suporta tanto as categorias HOME e ALTERNATIVE, Figura 4.1 Botões de menu

do aplicativo RestaurantFinder que invoca diversos aplicativos externos.

Servindo o RestaurantFinder com Intent 109 ele combinará com um Intent para HOME ou CATEGORY. Mas se o IntentFilter

não fornecer nenhuma categoria, ele não combinará com HOME ou CATEGORY. Você pode trabalhar com ações e categorias sem especificar nenhum dado. Usamos essa técnica na Activity ReviewList que criamos no Capítulo 3. Nesse exemplo, definimos o IntentFilter no XML de manifesto, como mostrado na listagem a seguir.

lisTagem 4.2 Declaração de manifesto da Activity ReviewList com <intent-filter>

<activity android:name="ReviewList" android:label="@string/app_name"> <intent-filter>

<category android:name="android.intent.category.DEFAULT" /> <action android:name="com.msi.manning.restaurant.VIEW_LIST" /> </intent-filter>

</activity>

Para combinar o filtro declarado nessa listagem, usamos o seguinte Intent no código, onde Constants.INTENT_ACTION_VIEW_LIST é a String"com.msi.manning.res­ taurant.VIEW_LIST":

Intent intent = new Intent(Constants.INTENT_ACTION_VIEW_LIST); startActivity(intent);

DADOS

Depois que o Android determinou que a ação e a categoria combinam, ele inspe- ciona os dados do Intent. Os dados podem ser do tipo MIME explícito ou uma combinação de esquema, autoridade e caminho. O Uri mostrada na Figura 4.2 é um exemplo do uso de esquemas, autoridade e caminhos.

O exemplo seguinte mostra com que se parece o uso de um tipo MIME explícito dentro de um URI:

audio/mpeg

As classes IntentFilter descrevem que combinação de tipo, esquema, autoridade e caminho é aceita. O Android segue um processo detalhado para determinar se há uma correspondência de Intent:

Se um esquema estiver presente e o tipo ausente, Intents com qualquer tipo irão se

corresponder.

Se um tipo estiver presente e o esquema ausente, Intents com qualquer esquema

irão se corresponder.

Se o esquema e o tipo estiverem ausentes, somente Intents sem esquema nem

tipo irão se corresponder.

Se uma autoridade for especificada, um esquema também deve ser especificado. Se um caminho for especificado, um esquema e uma autoridade também devem

ser especificados.

Figura 4.2 As partes de um URI

usadas no Android, mostrando esquema, autoridade e caminho.

weather:// com.msi.manning/loc?zip=12345

IntentFilter

<Intent-filter>

<action android:name=”android.intent.action.VIEW” />

<data android:scheme=”weather” android:host=”com.msi.manning” /> </Intent-filter>

Intent

Intent = newIntent(Intent.ACTION_VIEW

Uri.parse(”weather://com.msi.manning /loc?zip=12345”);

Figura 4.3 Exemplo de Intent e IntentFilter combinados usando um filtro definido em XML.

A maioria das correspondências é direta, mas, como você pode ver, elas podem ficar complicadas. Pense em Intent e IntentFilter como peças de um mesmo quebra-cabeça. Quando você chama um Intent em um aplicativo Android, o siste- ma decide que Activity, Service ou BroadcastReceiver irá executar sua re- quisição usando as ações, categorias e dados fornecidos. O sistema examina todas as peças do quebra-cabeça que possui até encontrar uma que combine com o Intent

que você forneceu e, então, encaixa essas peças para formar a conexão.

A Figura  4.3 mostra um exemplo de como ocorre uma correspondência. Esse exemplo define um IntentFilter com uma ação e uma combinação de um esque- ma e uma autoridade. Ele não especifica um caminho, então, qualquer caminho irá combinar. A figura também mostra um exemplo de Intent com um URI que combina com esse filtro.

Se múltiplas classes de IntentFilter se correspondem com o Intent forneci- do, a plataforma seleciona qual vai tratar o Intent. Para uma ação visível ao usuário como uma Activity, o Android geralmente apresenta ao usuário um menu pop-up que permite que ele selecione que Intent deve controlá-la. Para ações invisíveis como um broadcast, o Android considera a prioridade declarada de cada Intent­ Filter e dá a eles uma chance ordenada para tratar o Intent.

No documento Android em Ação - 3°. Edição (páginas 134-138)