Las intenciones

Una intención representa la voluntad de realizar alguna acción o tarea, como realizar una llamada de teléfono o visualizar una página web. Una intención nos permite lanzar una actividad o servicio de nuestra aplicación o de una aplicación diferente. Tienen un gran potencial en Android, por lo que resulta importante conocerlas y dominarlas.

video[TutorialLas intenciones en Android

Existen dos tipos de intenciones:>

  • Intenciones explícitas: se indica exactamente el componente a lanzar. Su utilización típica es la de ir ejecutando los diferentes componentes internos de una aplicación. Por ejemplo, desde la actividad Asteroides o MisLugares  lanzamos AcercaDeActivity por medio de una intención explicita.
  • Intenciones implícitas:  pueden solicitar tareas abstractas, como “quiero tomar una foto” o “quiero enviar un mensaje”. Además las intenciones se resuelven en tiempo de ejecución, de forma que el sistema mirará cuantos compomentes han registrado la posibilidad de ejecutar ese tipo deintención. Si encuentra varias el sistema puede preguntar al usuario el componente que prefiere utilizar.

Además, como se ha estudiado en el apartado "Comunicación entre actividades" las intenciones ofrecen un servicio de paso de mensajes que permite interconectar datos entre componentes.>

En concreto se utilizan intenciones cada vez que queramos:

  • Lanzar una actividad (startActivity() y startActivityForResult())

  • Lanzar un servicio (startService())

  • Lanzar un anuncio de tipo broadcast (sendBroadcast())

  • Conectarnos con un servicio (bindService())

En muchas ocasiones una intención no será inicializada por la aplicación, si no por el sistema, por ejemplo, cuando pedimos visualizar una página Web. En otras ocasiones será necesario que la aplicación inicialice su propia intención. Para ello se creará un objeto de la clase Intent.

Cuando se crea una Intención (es decir, se instancia un objeto de tipo Intent) esta contiene información de interés para que el sistema trate adecuadamente  la  intención o para el componente que recibe la intención. Puede incluir la siguiente información:>

Nombre del componente: Identificamos el componente que queremos lanzar con la intención. Hay que utilizar el nombre de clase totalmente cualificado que queremos lanzar  (org.example.asteroides.AcercaDeActivity). El nombre del componente es opcional. En caso de no indicarse se utilizará otra información de la intención para obtener el componente a lanzar. A este tipo de intenciones se les conocía como intenciones explícitas.

Acción: Una cadena de caracteres donde indicamos la acción a realizar o en caso de un Receptor de anuncios (Broadcast receiver), la acción que tuvo lugar y que queremos reportar. La clase Intent define una serie de constantes para acciones genéricas que se enumeran a continuación:

Algunas acciones estándar de las Intenciones

También puedes definir tus propias acciones. En este caso has de indicar el paquete de tu aplicación como prefijo. Por ejemplo: org.example.mislugares.MUESTRA_MAPA_LUGARES

Categoría: Complementa a la acción. Indica información adicional sobre el tipo de componente que ha de ser lanzado. El número de categoríaspuede ampliarse arbitrariamente. No obstante, en la clase Intent se definen una serie de categorías genéricas que podemos utilizar.


Algunas categorías estándar de las Intenciones

Una categoría suele utilizarse junto con una acción para aportar información adicional. Por ejemplo, indicaremos ACTION_MAIN a las actividades que  pueden utilizarse como puntos de entrada de una aplicación. Indicaremos además CATEGORY_LAUNCHER para que la actividad sea mostrada en la pantalla de inicio.

Datos: Referencia a los datos con los que trabajaremos. Hay que expresar estos datos por medio de una URI (el mismo concepto ampliamente utilizado en Internet). Ejemplos de URIs son: tel:963228525, http://www.androidcurso.com, content://call_log/calls… En muchos casos resulta importante saber el tipo de datos con el que se trabaja. Con este propósito se indica el tipo MIME asociado a la URI, es decir, se utiliza el mismo mecanismo que en Internet. Ejemplos de tipos MIME son text/xml, image/jpeg, audio/mp3…

Extras: Información adicional que será recibida por el componente lanzado. Está formada por un conjunto de pares variable/valor. Estas colecciones de valores se almacenan en un objeto de la clase Bundle. Su utilización ha sido descrita en la sección Comunicación entre actividades. Recordemos cómo se introducían estos valores en un Intent.

intent.putExtra("usuario", "Pepito Perez")
intent.putExtra("edad", 27);

En el apartado "Creación de nuevas actividades"  hemos aprendido a lanzar una actividad de forma explícita utilizando el constructor Intent(Context contexto, Class<?> clase). Por ejemplo, para lanzar la actividad AcercaDeActivity escribíamos:

Intent intent = new Intent(this, AcercaDeActicity.class);
startActivity(intent);

Para lanzar una actividad de forma implícita podemos usar el constructor Intent(String action, Uri uri). Por ejemplo:

Intent intent = new Intent(Intent.ACTION_DIAL,
                              URI.parse("tel:962849347");
startActivity(intent);

También se puede utilizar ActivityResultLauncher si esperamos que la actividad nos devuelva datos.

Ejercicio: Uso de intenciones implícitas

1.     Crea un nuevo proyecto con nombre Intenciones y tipo Empty Activity.

2.  El Layout de la actividad inicial ha de estar formado por cinco botones, tal y como se muestra a continuación:

3.     Abre la actividad principal e incorpora los siguientes métodos:

public void compartir(View view) {
   Intent intent = new Intent(Intent.ACTION_SEND);
   intent.setType("text/plain");
   intent.putExtra(Intent.EXTRA_TEXT,
          "Mira al sitio que he encontrado http://www.androidcurso.com/");
   startActivity(intent);
}

public void abrirPagina(View view) {
   Intent intent = new Intent(Intent.ACTION_VIEW,
        Uri.parse("http://www.androidcurso.com/"));
   startActivity(intent);
}

public void llamarTelefono(View view) {
   Intent intent = new Intent(Intent.ACTION_CALL,
        Uri.parse("tel:962849347"));
   startActivity(intent);
}

public void verMapa(View view) {
   Intent intent = new Intent(Intent.ACTION_VIEW,
            Uri.parse("geo:38.995656,-0.166093?z=18"));
   startActivity(intent);
}

public void tomarFoto(View view) {
   Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
   startActivity(intent);
}

public void mandarCorreo(View view) {
   Intent intent = new Intent(Intent.ACTION_SEND);
   intent.setType("text/plain");
   intent.putExtra(Intent.EXTRA_SUBJECT, "asunto");
   intent.putExtra(Intent.EXTRA_TEXT, "texto del correo");
   intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jtomas@upv.es"});
   startActivity(intent);
}

public void streetview(View view) {
   Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(
          "google.streetview:cbll=38.996766,-0.1652696&cbp=0,250,0,0,0"));
                       //cbll=latitud,longitud&cbp=0,azimut,0,zoom,altura
   startActivity(intent);
} 
fun compartir(view: View) = startActivity(
   Intent(Intent.ACTION_SEND).apply {
        type = "text/plain"
        putExtra(Intent.EXTRA_TEXT, 
         "Mira al sitio que he encontrado http://www.androidcurso.com/")})

fun abrirPagina (view: View) = startActivity(
   Intent(Intent.ACTION_VIEW, Uri.parse("http://www.androidcurso.com/")))

fun llamarTelefono(view: View) = startActivity(
   Intent(Intent.ACTION_DIAL, Uri.parse("tel:962849347")))

fun verMapa(view: View) = startActivity(
   Intent(Intent.ACTION_VIEW, Uri.parse("geo:41.656313,-0.877351")))

fun tomarFoto(view: View) = startActivity(
   Intent(MediaStore.ACTION_IMAGE_CAPTURE))

fun mandarCorreo(view: View) = startActivity(
   Intent(Intent.ACTION_SEND).apply {
        type = "text/plain"
        putExtra(Intent.EXTRA_SUBJECT, "asunto")
        putExtra(Intent.EXTRA_TEXT, "texto del correo")
        putExtra(Intent.EXTRA_EMAIL, arrayOf("jtomas@upv.es"))})

fun verMapa(view: View) = startActivity(
   Intent(Intent.ACTION_VIEW, Uri.parse(
          "google.streetview:cbll=38.996766,-0.1652696&cbp=0,250,0,0,0")))
                        //cbll=latitud,longitud&cbp=0,azimut,0,zoom,altura 

4.     Asocia el atributo onClick de cada uno de los botones al método correspondiente.

5.     Ejecuta la aplicación. Y selecciona botón COMPARTIR. Observa como el sistema pregunta al usuario a través de que aplicación quiere compartir

6.    Selecciona WhatsApp y verifica como te permite mandar el mensaje indicado en el código.
7.    El segundo botón, ABRIR PÁGINA WEB, ha de funcionar sin problemas
8.    Si seleccionas el tercer botón la aplicación se detendrá. En el LogCat, encontrarás la línea:
 

  Caused by: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.CALL
Indica que se ha intentado llamar por teléfono sin tener concedido el permiso para ello.

NOTA: En el capítulo 7 estudiarás el tema de la seguridad. Aprenderás cómo has de solicitar el permiso adecuado si quieres que tu aplicación pueda llamar por teléfono.
9.   Vamos a ver una alternativa que te permitirá resolver el problema sin tener que pedir este permiso. En el método llamarTelefono(), reemplaza ACTION_CALL por ACTION_DIAL y vuelve a ejecutar la aplicación. Ahora no se producirá el error, si no que se abrirá la aplicación de llamar por teléfono con el número marcado. Es el usuario quien decidirá si es seguro llamar a este número.
10.  Verifica que el resto de los botones funcionan correctamente.
11.  Trata de personalizar los valores que son enviados o visualizados en cada intención y vuelve a ejecutar la aplicación.
12. Serías capaz de modificar los datos del botón de Streetview para que muestre el cartel que aparece en la puerta de la cafetería de la EPSG, desde la entrada de la calle. Ha de aparecer con el zoom máximo (3) y lo más centrado que puedas tanto horizontal como vertical.

Recursos adicionales: Tabla con intenciones que podemos utilizar de aplicaciones Google

Aplicación

URI

Acción

Resultado

Navegador

http://dirección_web
https://dirección_web

VIEW

Abre una ventana de navegador con una URL.

"" (cadena vacía)

http://dirección_web
https://dirección_web

WEB_SEARCH

Realiza una búsqueda web. Se indica la cadena de búsqueda en el extra SearchManager.QUERY 

Teléfono

tel:número_teléfono

CALL

Realiza una llamada de teléfono. Los números válidos se definen en IETF RFC 3966 . Entre estos se incluyen: tel:2125551212 y tel:(212)5551212. Necesitamos el permiso android.permission.CALL_PHONE

tel:número_teléfono
voicemail:

DIAL

Introduce un número sin llegar a realizar la llamada.

Google Maps

geo:latitud,longitud
geo:lat,long?z=zoom
geo:0,0?q=dirección
geo:0,0?q=búsqueda

VIEW

Abre la aplicación Google Maps para una localización determinada. El campo z específica el nivel de zum.

Google Streetview

google.streetview: cbll=latitud,longitud& cbp=1,yaw,pitch,zoom& mz=mapZoom

VIEW

Abre la aplicación Street View para la ubicación dada. El esquema de URI se basa en la sintaxis que utiliza Google Maps. Solo el campo cbll es obligatorio.

 

Preguntas de repaso: Intenciones