Como enviar o usuário para outro aplicativo

Uma das características mais importantes do Android é a habilidade do aplicativo de enviar o usuário para outro aplicativo com base em uma “ação” que gostaria de executar. Por exemplo, se o aplicativo tiver o endereço de um negócio que você gostaria de mostrar em um mapa, não será necessário criar uma atividade no aplicativo que mostre um mapa. Em vez disso, é possível criar uma solicitação para exibir o endereço usando uma Intent. O sistema Android inicia um aplicativo que possa mostrar o endereço em um mapa.

Como explicado na primeira lição, Criação do seu primeiro aplicativo, use intents para navegar entre atividades no aplicativo. Geralmente, isso é feito com um intent explícito que define o nome exato da classe do componente que você deseja iniciar. No entanto, quando desejar que outro aplicativo execute uma ação, como “visualizar um mapa”, será preciso usar um intent implícito.

Esta lição mostra como criar um intent implícito para uma ação específica e como usá-la para iniciar uma atividade que executa a ação em outro aplicativo.

Criar um intent implícito

Intents implícitos não declaram o nome da classe do componente a iniciar, mas declaram uma ação a executar. A ação especifica o que deve ser feito, como visualizar, editar, enviar ou obter algo. Geralmente, os intents incluem dados associados à ação, como o endereço que deseja visualizar ou a mensagem de e-mail a ser enviada. Dependendo do intent que deseja criar, os dados podem ser Uri, um dos outros tipos de dados ou o intent pode não precisar de dado algum.

Se os dados forem uma Uri, há um construtor simples Intent() que poderá ser usado para definir a ação e os dados.

Este é um exemplo de como criar um intent para iniciar uma chamada telefônica usando os dados de Uri para especificar o número de telefone:

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

Quando o aplicativo invoca o intent chamando startActivity(), o aplicativo Telefone inicia uma chamada para o número especificado.

Estas são algumas outros intents e suas ações e pares de dados de Uri :

  • Visualizar um mapa:
    // Map point based on address
    Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
    // Or map point based on latitude/longitude
    // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
    Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
    
  • Visualizar uma página da web:
    Uri webpage = Uri.parse("http://www.android.com");
    Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
    

Outros tipos de intents implícitos exigem dados “extras” que fornecem diferentes tipos de dados, como uma cadeia de caracteres. É possível adicionar um ou mais dados extras usando vários métodos putExtra().

Por padrão, o sistema determina o tipo MIME adequado que um intent exige com base nos dados de Uri incluídos. Se você não incluir uma Uri no intent, sempre use setType() para especificar o tipo de dado associado ao intent. Definir o tipo de MIME especifica melhor que tipos de atividades receberão o intent.

Estas são mais alguns intents que adicionam dados extras para especificar a ação desejada:

  • Enviar um e-mail com um anexo:
    Intent emailIntent = new Intent(Intent.ACTION_SEND);
    // The intent does not have a URI, so declare the "text/plain" MIME type
    emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
    emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
    emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
    // You can also attach multiple items by passing an ArrayList of Uris
    
  • Criar um evento de calendário:
    Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
    Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
    Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
    calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
    calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
    calendarIntent.putExtra(Events.TITLE, "Ninja class");
    calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
    

    Observação: Esse intent para evento de calendário é compatível apenas com nível de API 14 e superior.

Observação: É importante definir a Intent para ser a mais específica possível. Por exemplo, se você deseja exibir uma imagem usando o intent ACTION_VIEW, especifique o tipo de MIME do image/*. Isso evita que aplicativos que podem “exibir” outros tipos de dados (como um aplicativo de mapas) sejam acionados pelo intent.

Verificar se há um aplicativo para receber o intent

Embora a plataforma do Android garanta que determinados intents sejam resolvidos com um dos aplicativos embutidos (como aplicativo de Telefone, E-mail ou Agenda), sempre inclua uma etapa de confirmação antes de chamar um intent.

Atenção: Se você invocar um intent e não houver um aplicativo disponível no dispositivo para processar o intent, o aplicativo falhará.

Para confirmar se há atividade disponível para responder ao intent, chame queryIntentActivities() para obter uma lista de atividades que podem processar a Intent. Se o List retornado não estiver vazio, o intent poderá ser usada com segurança. Por exemplo:

PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
        PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;

Se isIntentSafe for true, pelo menos um aplicativo responderá ao intent. Se for false, não há aplicativos disponíveis para processar o intent.

Observação: Faça essa verificação quando a atividade iniciar, caso seja necessário desativar a funcionalidade que usa o intent antes de o usuário tentar usá-la. Se você conhecer um aplicativo específico que lide com o intent, forneça um link para que o usuário o baixe (veja como vincular para seus produtos no Google Play).

Iniciar uma atividade com o intent

Figura 1. Exemplo de diálogo de seleção que aparece quando mais de um aplicativo pode processar um intent.

Quando tiver criado sua Intent e definido as informações extras, chame startActivity() para enviá-la ao sistema. Se o sistema identificar mais de uma atividade que pode processar o intent, um diálogo será exibido para que o usuário selecione qual aplicativo usar, como mostrado na figura 1. Se houver apenas uma atividade para processar o intent, o sistema a iniciará imediatamente.

startActivity(intent);

Este é um exemplo completo que mostra como criar um intent para exibir um mapa, confirmar se há um aplicativo para processar o intent e iniciá-lo:

// Build the intent
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// Verify it resolves
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;

// Start an activity if it's safe
if (isIntentSafe) {
    startActivity(mapIntent);
}

Mostrar um seletor de aplicativo

Figura 2. Caixa de diálogo seletora.

Observe que, ao iniciar uma atividade passando a Intent para startActivity() e quando há mais de um aplicativo que responde ao intent, o usuário pode selecionar qual aplicativo usar por padrão (marcando uma caixa de seleção na parte inferior da caixa de diálogo, veja a figura 1). Isso é bom ao executar uma ação para qual o usuário deseja usar o mesmo aplicativo todas as vezes, como quando abre uma página da web (o usuário geralmente usa apenas um navegador) ou para tirar fotos (o usuário prefere uma câmera).

Contudo, se a ação a ser executada puder ser processada por vários aplicativos e o usuário preferir um aplicativo diferente a cada vez— como a ação “compartilhar” em que os usuários podem ter vários aplicativos para compartilhar um item—você deverá exibir explicitamente um diálogo seletor conforme mostrado na figura 2. O diálogo seletor força o usuário a selecionar qual aplicativo usar para a ação todas as vezes (o usuário não pode selecionar um aplicativo padrão para a ação).

Para mostrar o seletor, crie uma Intent usando createChooser() e passe-a para startActivity(). Por exemplo:

Intent intent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);

// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

Isso exibe um diálogo com uma lista de aplicativos que respondem ao intent passado ao método createChooser() e usa o texto fornecido como título da caixa de diálogo.