Intents implícitos. Permisos. Filtros.

De Manuais Informática - IES San Clemente.
Ir a la navegación Ir a la búsqueda

Introdución

  • Imos continuar coa aplicación desenvolvida no apartado anterior: U3_20_Intents.
  • Engadiránselle, permisos, filtros, e intents implícitos.

Android 2014 U3 20 LanzarActivity 16.jpg

Permisos

  • Cando instalamos unha aplicación nun dispositivo real (non nun AVD) se precisa acceder a características que esixen algún tipo de permiso, o proceso de instalación pregunta se estamos dispostos a dar eses permisos para que a aplicación poida funcionar con tódalas súas funcionalidades.
  • Por exemplo, instalando Gmail:

Gmail.png

  • O proceso de instalación pregunta ao usuario se por exemplo lle deixa acceder a esta aplicación á súa lista de contactos.
  • No ficheiro AndroidManifest.xml é onde se declaran os permisos que precisa a aplicación para poder facer uso de funcionalidades protexidas: contactos, cámara, mermoria usb, gps, etc.
  • A través de unha ou varias etiquetas <uses-permission> vanse declarar os permisos que precisa a aplicación.

Exemplos de permisos no ficheiro AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.u3_20_intents"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".U3_20_Intents"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".RecibirDatos"
            android:label="@string/title_activity_recibir_datos" >
        </activity>
    </application>

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

</manifest>
  • Liña 31: Permiso que "permite" realizar unha chamada de telefono sen pasar a través do interface do teléfono para que o usuario marque.
  • Liña 32: Permítelle á aplicación abrir conexións de rede.
  • Liña 33: Da súa lectura pódese concluír o que permite.
  • Tamén se pode realizar de modo gráfico.
  • No ficheiro AndroidManifest.xml premer en Permissions

Android 2014 U3 20 LanzarActivity 15.jpg

  • Lembrar que os permisos asígnanse no momento da instalación a aplicación. Nun dispositivo real pídeselle consentimento ao usuario, non así nun AVD.

Chamadas a intents de modo implícito

  • Como xa se dixo, un compoñente pode ser lanzado de forma implícita cando se indica a acción que se desexa realizar e se é o caso os datos sobre os que se desexa realizar a acción.
  • Non se vai especificar cal é a activity que vai atender o intent. Incluso se hai varias Activities que poidan atender ese intent o sistema ofrecerá ao usuario as distintas posibilidades para que escolla.
  • Por exemplo, cando dende contactos se desexa enviar un mensaxe a un número de teléfono o sistema ofrece a posibilidade de que se envíe a través de sms, Whatsapp, Viber, etc, se se teñen instalados estes últimos.
  • A seguinte imaxe amosa un exemplo no que para abrir unha URL hai dúas aplicacións que o poden facer.

Android implicit intent choice chrome.png


  • Para lanzar un intent de modo implícito precísase indicar:
    • Acción (action): A acción que se desexa levar a cabo. Por exemplo,
      • ACTION_VIEW, para mostrar datos ao usario
      • ACTION_EDIT, para editar os datos que nos pasan
      • ACTION_PICK. selecciona un ítem dun conxunto de datos e devolve o selccionado.
      • ACTION_WEB_SEARCH. busca no navegador as palabras indicadas.
      • etc.
    • Datos (data): os datos sobre os que se vai operar, por exemplo, unha url, os datos dun contacto,a cadea de busca, etc.
  • Exemplo:
    • ACTION_VIEW content://contacts/people/1 -- Amosa a información sobre a persoa con identificador 1.


Filtros de intencións (Intent Filters)

  • Android busca os compoñentes que poden responder a unha Acción nos filtros de intención que se definen no ficheiro AndroidManifest.xml de tódalas aplicacións que están instaladas no dispositivo.
  • Cando se constrúe unha activity nunha aplicación, pódese indicar os filtros de intención de manifestan que esa activity pode dar resposta as Accións que lanzan outras aplicacións.


  • No noso caso, imos modificar un chisco o código da actividade secundaria para que poida atender a peticións de visionar urls de tipo http.
  • Así cando se lance, por exemplo, que se desexa ver http://www.google.es o sistema vai ofrecer 2 opcións: o navegador de internet e a nosa actividade secundaria do proxecto (RecibirDatos).

Android 2014 U3 20 LanzarActivity 22.jpg


  • Para iso é preciso definir que esa Activity pode atender Accións de visionado de datos tipo http.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.u3_20_intents"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".U3_20_Intents"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".RecibirDatos"
            android:label="@string/title_activity_recibir_datos" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:scheme="http" />
            </intent-filter>
        </activity>
    </application>

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

</manifest>
  • Liñas 28 e 25: delimitan os filtros de intencións para a activity RecibirDatos.
  • Liña 29: indica para que tipo de accións esta dispoñible esta activity.
  • Liña 30: A categoría indica as circunstancias nas que se debe desenvolver a acción.
  • Liña 33: o tipo de datos que pode atender esta activity cando haxa unha intención preguntando por recursos http.

Caso práctico

  • A continuación imos engadir unha serie de botóns, modificar o código, etc ao proxecto.
  • Continuar co proxecto U3_20_Intents.


XML do Layout principal

  • Engadiuse unha serie de botóns, todos chaman ao mesmo método. (Liñas 51-91)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Dime o teu nome" />

        <EditText
            android:id="@+id/et_nome"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <CheckBox
        android:id="@+id/chk_destruir"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:checked="false"
        android:text="Destruír esta activity ao chamar á 2ª" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Chamadas explícitas a intents"
        android:textColor="#00F" />

    <Button
        android:id="@+id/btn_enviar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onEnviarClick"
        android:text="Chamar 2ª Activity: Recibir Datos" />

    <Button
        android:id="@+id/btn_calculadora"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onCalculadoraClick"
        android:text="Calculadora" />

    <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal"
       android:text="Chamadas implícitas a intents"
       android:textColor="#00F" />
 
    <Button
       android:id="@+id/btn_amosar_contactos"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="chamarIntent"
       android:text="Amosar contactos" />
 
    <Button
       android:id="@+id/btn_seleccionar_contacto"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="chamarIntent"
       android:text="Seleccionar contacto" />
 
    <Button
       android:id="@+id/btn_chamar_tel"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="chamarIntent"
       android:text="Chamar por teléfono" />
 
    <Button
       android:id="@+id/btn_marcar_tel"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="chamarIntent"
       android:text="Marcar nº de teléfono" />
 
    <Button
       android:id="@+id/btn_navegador"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="chamarIntent"
       android:text="Abrir navegador*" />

</LinearLayout>

Código Java da activity principal

package com.example.u3_20_intents;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.Menu;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;

public class U3_20_Intents extends Activity {

	public final static String NOME = "com.example.NOME";
	private static final int COD_PETICION = 33;
	private static final int COD_CONTACTOS = 7;

	TextView tvNome;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_u3_20__intents);
		tvNome = (TextView) findViewById(R.id.et_nome);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.u3_20__intents, menu);
		return true;
	}

	public void onEnviarClick(View view) {
		CheckBox chkDestruir = (CheckBox) findViewById(R.id.chk_destruir);

		Intent intent = new Intent(this, RecibirDatos.class);
		intent.putExtra(NOME, tvNome.getText().toString());

		// startActivity(intent);
		startActivityForResult(intent, COD_PETICION);

		if (chkDestruir.isChecked())
			finish();
	}

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

		if (requestCode == COD_PETICION) {
			if (resultCode == RESULT_OK) {
				if (data.hasExtra("APELIDO"))
					Toast.makeText(this, tvNome.getText() + "\nO teu apelido é: " + data.getExtras().getString("APELIDO"), Toast.LENGTH_SHORT).show();

			} else
				Toast.makeText(this, "Saíches da actividade secundaria sen premer o botón Pechar", Toast.LENGTH_SHORT).show();
		} else if (requestCode == COD_CONTACTOS && resultCode == RESULT_OK) {
			Uri contactoData = data.getData();
			Cursor c = managedQuery(contactoData, null, null, null, null);
			if (c.moveToFirst()) {
				String nombre = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
				Toast.makeText(this, "Contacto: " + nombre, Toast.LENGTH_LONG).show();
			}
		}

	}

	public void onCalculadoraClick(View v) {

		Intent intent = new Intent();
		intent.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");

		startActivity(intent);
	}

	public void chamarIntent(View view) {
		Intent intent = null;
		switch (view.getId()) {
		case R.id.btn_seleccionar_contacto:
			intent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts/people/"));
			startActivityForResult(intent, COD_CONTACTOS);
			break;

		case R.id.btn_amosar_contactos:
			intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/"));
			startActivity(intent);
			break;

		case R.id.btn_chamar_tel:
			intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+34)981445566"));
			startActivity(intent);
			break;

		case R.id.btn_marcar_tel:
			intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+34)986112233"));
			startActivity(intent);
			break;

		case R.id.btn_navegador:
			intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.es/"));
			startActivity(intent);
			break;
		}
	}

	public void finish() {
		super.finish();
		Toast.makeText(this, "Mataches a actividade principal", Toast.LENGTH_SHORT).show();
	}

}
  • Liña 19: Créase unha nova constante de tipo enteiro cun valor calquera para cando chamemos a activity de contactos para que nos devolva un contacto.
  • Liñas 59-66: Revisamos cando se volva dunha actividade secundaria, se é a de Contactos. Nese caso (escápase aos obxectivos desta unidade) créase un cursos para procesar os datos recibidos da activity contactos.
  • Liñas 78-106: Procesado dos distintos botóns, creación dos intents en función do tipo de acción e datos que se desexan procesar.
  • Liñas 82 e 83: Observar como se chama a activity de contactos para que logo nos devolva o contacto seleccionado.



XML do Layout da Activity Secundaria: RecibirDatos

  • Non hai ningún cambio con respecto ao proxecto anterior.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_resultado"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="resultado"
        android:textSize="20sp" />

    <EditText
        android:id="@+id/et_apelido"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:hint="Introduce o teu apelido" />

    <Button
        android:id="@+id/btn_pechar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="onPecharClick"
        android:text="Pechar" />
</LinearLayout>

O código Java da Activity Secundaria: RecibirDatos

package com.example.u3_20_intents;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class RecibirDatos extends Activity {
	// String Forma_Pechar_Activity;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_recibir_datos);
		// Forma_Pechar_Activity = " Premendo botonera Retroceso";

		TextView tvResultado = (TextView) findViewById(R.id.tv_resultado);

		Intent intent = getIntent();

		if ("http".equals(intent.getScheme()))

			tvResultado.setText("URL: " + intent.getDataString());
		else
			tvResultado.setText("Ola " + intent.getExtras().getString(U3_20_Intents.NOME));

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.recibir_datos, menu);
		return true;
	}

	public void onPecharClick(View view) {
		// Forma_Pechar_Activity = " Premendo botón Pechar";
		EditText et_apelido = (EditText) findViewById(R.id.et_apelido);

		Intent datos_volta = new Intent();
		datos_volta.putExtra("APELIDO", et_apelido.getText().toString());
		setResult(RESULT_OK, datos_volta);
		finish();

	}

	public void finish() {
		super.finish();
		// Toast.makeText(this, "Saíches da actividade secundaria: " +
		// Forma_Pechar_Activity, Toast.LENGTH_SHORT).show();
	}

}
  • Liñas 24-28: Engadiuse a posibilidade de poder procesar intents cuxo esquema (getSchema) sexa de tipo http. Nese caso simplemente amosamos a URL á que desexaba conectarse o usuario.





-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2015).