Mostrando postagens com marcador Intents Nativas. Mostrar todas as postagens
Mostrando postagens com marcador Intents Nativas. Mostrar todas as postagens

segunda-feira, 13 de junho de 2016

Chrome Custom Tabs para Android

Olá povo,

Mais um post rápido :) Quando precisamos abrir uma URL dentro de uma aplicação Android normalmente utilizamos uma Intent como a seguir:
Intent it = new Intent(Intent.ACTION_VIEW, 
                       Uri.parse("http://www.nglauber.com.br"));
startActivity(it);
O problema de usar essa abordagem é que exige o carregamento de outro aplicativo (o que é pesado computacionalmente falando) e fará com que o usuário deixe seu aplicativo, o que não é bom. Outro ponto negativo é que uma vez que você não tem acesso ao outro aplicativo (o browser nesse caso), você não consegue fazer nenhuma customização.

Uma outra abordagem é utilizar o componente WebView.
WebView webView = (WebView)findViewById(R.id.webView);
webView.loadUrl("http://www.nglauber.com.br");
webView.setWebViewClient(new WebViewClient() {
    public boolean shouldOverrideUrlLoading(WebView view, String url){
        view.loadUrl(url);
        return false; 
    }
});
Nesse caso você possui um controle maior, uma vez que tudo é feito dentro do seu aplicativo. Entretanto, você terá que fazer vários controles para a navegação (como eu fiz aqui tratando o redirecionamento de página). Um problema aqui é que o WebView não compartilha a sessão do browser.

Chrome Custom Tabs junta os pontos positivos de ambas as abordagens, pois permite o controle da experiência web dentro do seu aplicativo. Com essa API podemos: definir transições customizadas; personalizar título; adicionar ações personalizadas; fazer um pré-carregamento da página para agilizar o carregamento; entre outros.
Como pode-se imaginar, esse recurso só funcionará se o usuário possuir o Chrome instalado no aparelho. Caso contrário, será disparada a Intent que mostramos no início do post.
 Para usar o Chrome Custom Tabs, a primeira coisa a fazer é adicionar a dependência no build.gradle.
dependencies {
    ...
    compile 'com.android.support:customtabs:23.3.0'
}
Então é só chamar a aba como a seguir:
String url = "http://www.nglauber.com.br";
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();

// Definindo a cor da toolbar (opcional)
builder.setToolbarColor(ActivityCompat.getColor(this, R.color.colorPrimary));

// Adicionando uma ação/menu (opcional)
Bitmap icon = BitmapFactory.decodeResource(
        getResources(), android.R.drawable.ic_menu_agenda);
PendingIntent pit = PendingIntent.getActivity(
        this, 0, new Intent(this, MainActivity.class), 0);

// Ação
builder.setActionButton(icon, "Ação", pit, true);
// Menu
builder.addMenuItem("Menu", pit);

// Definindo animações (opcional)
builder.setStartAnimations(this, 
        R.anim.slide_in_right, R.anim.slide_out_left);
builder.setExitAnimations(this, 
        R.anim.slide_in_left, R.anim.slide_out_right);

// Abrindo a "aba"
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(this, Uri.parse(url));

Como podemos observar, é bastante simples criar as custom tabs do Chrome. Criamos uma instância da classe CustomTabsIntent.Builder e com ela criamos podemos customizar a aba da maneira que desejarmos. Primeiro definimos a cor do título usando o método setToolbarColor(int). Em seguida instancimamos um Bitmap e uma PendingIntent que podem ser utilizadas para adicionar uma ação ou uma opção de menu na barra de título. A ação é adicionada por meio do método setActionButton(Bitmap,String,PendingIntent,boolean) e o menu por meio do método addMenuItem(String,PendingIntent).
As animações foram definidas utilizando o método setStartAnimations e setExitAnimations. Essas animações foram definidas como a seguir:
// res/anim/slide_in_left.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="-100%p" android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

// res/anim/slide_in_right.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="100%p" android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

// res/anim/slide_out_left.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0" android:toXDelta="-100%p"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

// res/anim/slide_out_right.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0" android:toXDelta="100%p"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>
Por fim, criamos uma instância da classe CustomTabsIntent e com o método launchUrl(Activity, Uri) abrimos essa nova aba.
Abaixo podemos ver a aplicação em execução.

Mais detalhes aqui:
https://developer.chrome.com/multidevice/android/customtabs

4br4ç05,
nglauber

domingo, 25 de outubro de 2009

Intents nativas do Android

Olá povo,

Um grande benefício que a plataforma Android trouxe para nós desenvolvedores foi a capacidade de nos comunicar com aplicações "nativas" através de intenções (Intents).
Sendo assim, resolvi publicar algumas das intents nativas mais comuns do Android. Segue abaixo o código-fonte.


public class ExemploIntents extends ListActivity {

private static final String[] OPCOES = {
"Browser",
"Realizando uma chamada",
"Visualizar contato",
"Todos os contatos",
"Mapa",
"Tocar música",
"SMS",
"Sair"
};

@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
OPCOES);

setListAdapter(adapter);
}

@Override
protected void onListItemClick(ListView l, View v,
int position, long id) {

super.onListItemClick(l, v, position, id);
Uri uri = null;
Intent intent = null;

switch (position) {
// Abrindo uma URL
case 0:
uri = Uri.parse("http://nglauber.blogspot.com");
intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
break;

// Realiza uma chamada
case 1:
uri = Uri.parse("tel:99887766");
intent = new Intent(Intent.ACTION_DIAL, uri);
startActivity(intent);
break;

// Visualiza um contato específico
// da lista de contatos
case 2:
uri = Uri.parse(
"content://contacts/people/5");
intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
break;

// Visualiza todos os contatos e permite
// selecionar um através do resultado
// da Activity
case 3:
uri = Uri.parse(
"content://contacts/people/");
intent = new Intent(Intent.ACTION_PICK, uri);
startActivityForResult(intent, 0);
break;

// Pesquisa uma posição do mapa
// !Seu AVD deve estar usando Google APIs!
case 4:
uri = Uri.parse(
"geo:0,0?q=Rua+Amelia,Recife");
intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
break;

// Executa uma música do SDcard
case 5:
uri = Uri.parse(
"file:///sdcard/musica.mp3");
intent = new Intent();
intent.setDataAndType(uri,"audio/mp3");
startActivity(intent);
break;

// Abrindo o editor de SMS
case 6:
uri = Uri.parse("sms:12345");
intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra("sms_body", "Corpo do SMS");
startActivity(intent);
break;

default:
finish();
}
}

@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {

super.onActivityResult(requestCode,
resultCode, data);

// Mostra um contato selecionado (case 3)
// em um Toast
if (data == null){
Toast.makeText(this, "Nenhum contato",
Toast.LENGTH_SHORT).show();
} else {
Uri uri = data.getData();
Toast.makeText(this, "Contato: "+ uri,
Toast.LENGTH_SHORT).show();
}
}
}


Vamos explicar o que foi feito acima. Criamos uma lista com várias opções de intents nativas. E quando o usuário clicar em qualquer uma dessas opções, a respectiva Intent será disparada.
Em todos os casos, utilizamos o objeto Uri para criar a Intent. Esse objeto indica um recurso do aparelho queremos acessar, e baseado no protocolo informado, ele irá disparar a atividade desejada.
Em conjunto com a Uri, associamos uma ação que queremos realizar sobre o recurso. Vamos exemplificar como o Android entende a solicitação, usando o caso do Browser: "O usuário está com a intenção (Intent) de visualizar (ACTION_VIEW) o recurso (Uri) http://nglauber.blogspot.com". Nesse momento o Android faz uma busca interna pra saber quem pode tratar essa intenção.

No exemplo de discar um número, utilizamos a ação ACTION_DIAL e o protocolo "tel:" seguido do número do telefone a ser discado. Notem que aqui há uma diferença entre "discar" (ACTION_DIAL) e "chamar" (ACTION_CALL). A primeira opção apenas disca o número não chama. Se quiséssemos chamar o número ao invés de apenas discá-lo, deveríamos utilizar a ACTION_CALL e adicionar a permissão abaixo no manifest:

<uses-permission name="android.permission.CALL_PHONE"/>

Na lista de contatos temos dois casos. O primeiro visualiza um contato utilizando o protocolo "content://" - que identifica um ContentProvider - passando o caminho do provider de contatos. Já o segundo caso está usando a ação ACTION_PICK para recuperar a Uri de um contato específico. Para tal, é utilizado o método startActivityForResult que iniciará a tela de contatos permitindo que selecionemos um da lista. Para tratar o retorno da atividade, utilizamos o método onActivityResult.
Para abrir a aplicação de Mapas em um local específico utilizamos o protocolo "geo:" seguido do do endereço do local desejado. É possível passar também a longitude e latitude (geo:lat,long).
Para executarmos o MP3 Player padrão do aparelho passando uma música, utilizamos o método setDataAndType e passamos a Uri com o protocolo "file://" e informando o MIME type do arquivo.
Mais informações aqui.

4br4ç05,
nglauber