viernes, 5 de septiembre de 2014

Intenciones y filtros de intenciones

Una intención (Intent) es un objeto que utilizaremos para iniciar un componente desde otro componente. Aunque las intenciones facilitan la comunicación entre componentes de varias maneras, hay tres casos de uso fundamentales:

  • Para iniciar una actividad (Activity). Una actividad representa una pantalla de nuestra aplicación. Podemos iniciar una actividad pasando una intención como parámetro del método startActivity(). La intención describe qué actividad iniciar y transportará cualesquiera otros datos que fueran necesarios.

    Si además queremos recibir algún tipo de resultado desde la actividad cuando ésta finaliza, utilizaremos el método startActivityForResult(). La actividad que originó la solicitud, recibirá el resultado a través de una intención a la que podremos acceder desde su evento onActivityResult().

  • Para iniciar un servicio (Service). Un servicio es un componente que realiza operaciones en segundo plano y que no cuenta con una interfaz de usuario. Puedes iniciar un servicio para realizar una operación (descargar un archivo, por ejemplo) pasando una intención como parámetro al método startService(). La intención describe el servicio a iniciar y transportará cualesquiera otros datos que fueran necesarios.

    Si el servicio cuenta con una interfaz cliente-servidor, podrás enlazar el servicio desde un componente pasando una intención como parámetro del método bindService().

  • Para la entrega de avisos (BroadcastReceiver). Un aviso es un mensaje que cualquier aplicación podrá recibir y que se genera como consecuencia de un evento concreto. El sistema avisa de ciertos eventos tales como que el sistema está arrancando, o que se ha iniciado la carga de batería. Podremos enviar avisos a otras aplicaciones pasando una intención como parámetro de los métodos sendBroadcast(), sendOrderedBroadcast(), o sendStickyBroadCast().

Tipos de intenciones.

Las intenciones pueden ser de dos tipos:

  • Explícitas. Una intención explícita especifica el componente que quiere iniciar a través de su nombre de clase. Utilizaremos una intención de este tipo para iniciar un componente de nuestra propia aplicación. Por ejemplo, iniciar una nueva actividad en respuesta a la acción de un usuario o iniciar un servicio para descargar un archivo en segundo plano.

  • Implícitas. En este caso, no especificaremos el nombre de una clase para hacer referencia al componente que queremos iniciar. En su lugar, especificaremos una acción a realizar. Por ejemplo, si necesitamos mostrar al usuario una ubicación en el mapa (acción), podemos usar una intención de este tipo para mostrar dicha ubicación con la aplicación adecuada.

Justo cuando creemos una intención explícita, el sistema inicia el componente de aplicación especificado en la intención.

Cuando creamos una intención implícita, el sistema Android localiza el componente más apropiado comparando la acción especificada en la intención con las acciones especificadas en los filtros de intenciones, definidos en los archivos manifest, de cada una de las aplicaciones del dispositivo. Si solo existe un filtro que coincide con la acción solicitada, el sistema inicia el componente y le entrega la intención. Si la acción solicitada coincide con más de un filtro, el sistema mostrará un cuadro de diálogo desde el que el usuario podrá seleccionar la aplicación deseada para realizar la acción. Por último, si la acción solicitada no encuentra candidatos, se producirá un error.

Un filtro de intenciones es un elemento que utilizaremos en el archivo manifest de una aplicación para definir el tipo de intenciones que es capaz de tratar un determinado componente. Por ejemplo, declarando un filtro de intenciones para una actividad, estaremos definiendo un nuevo punto de entrada en nuestra aplicación y permitiendo a otras aplicaciones que puedan invocarla. Si por el contrario, no defines ningún filtro de intenciones para una actividad, ésta solo podrá ser invocada a través de una intención explícita.

Solicitar una intención implícita
Imagen 1. Solicitando una intención implícita al sistema.
[1] Activity A crea la intención con la acción asociada y solicita un candidato al sistema llamando al método startActivity().
[2] El sistema Android recibe la intención, busca coincidencias entre la acción solicitada y los filtros de intenciones de las aplicaciones.
[3] El sistema ha encontrado un candidato e inicia el componente Activity B.

Importante. Para garantizar la seguridad nuestra aplicación, usa siempre intenciones explícitas cuando quieras iniciar un servicio. Utilizar intenciones implícitas para iniciar un servicio es poco seguro porque no sabremos con certeza qué servicio atenderá la petición y el usuario no puede ver qué servicio se inicia.

Creando una intención.

Una intención transporta información que el sistema Android usa para determinar el componente que tiene que invocar. Además, la intención también especificará información adicional para que el componente receptor pueda realizar la acción solicitada de la manera adecuada.

La información asociada a una intención es la siguiente:

  • Nombre del componente.

    Se trata del componente que queremos invocar. Se utiliza para declarar intenciones explícitas donde la intención será entregada a un componente de aplicación concreto. Si la intención no cuenta con este nombre, ésta será implícita y será el sistema el encargado de entregar la intención basándose en otra información relacionada con la intención: acción, datos, categoría, etc.

    El nombre del componente es una instancia de la clase ComponentName. Usa el nombre completo (incluyendo el nombre del paquete de la aplicación) para especificar el nombre del componente destino. Por ejemplo, com.example.ExampleActivity. Puedes asignar el nombre del componente utilizando los método setComponent(), setClass(), setClassName(), o utilizando el constructor de la clase Intent.

  • Acción.

    Una cadena especificando la acción a realizar (visualizar, enviar, seleccionar, etc.).

    En el caso de intenciones para la comunicación de avisos, estaríamos hablando de la acción que se está realizando y es comunicada. La acción determina cómo se va a estructurar la información de la intención relacionada con los datos y los extras.

    También podrás especificar tus propias acciones, generalmente para ser usadas por otras aplicaciones. Como norma general, utilizaremos constantes que ya se encuentran definidas en la clase Intent:
    • Intent.ACTION_VIEW. Esta acción la usaremos para indicar que queremos mostrar al usuario cierta información a través de la actividad adecuada. Por ejemplo, una ubicación a través de una aplicación de mapas.
    • Intent.ACTION_SEND. Esta acción la usaremos cuando queramos compartir alguna información a través de otra aplicación. Por ejemplo, una aplicación de correo electrónico o una aplicación relacionada con alguna red social.

    Para ver un listado detallado de las acciones definidas en la clase Intent, puedes consultarlo en el manual de referencia. Otras acciones las encontraremos definidas en la clase Settings y que nos servirán para abrir ciertas pantallas de configuración del sistema.

    Para asociar una acción a una intención, lo haremos desde su método setAction, o desde su constructor.

    Si defines tus propias acciones, recuerda incluir el nombre del paquete de tu aplicación como prefijo para evitar posibles colisiones:
    static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
    

  • Datos.

    Un URI (objeto de la clase URI) a los datos sobre los que se quiere actuar y/o el tipo MIME de los datos.

    A veces, cuando creamos una intención, será importante que especifiquemos el tipo MIME de los datos. Por ejemplo, una actividad que pueda visualizar imágenes, probablemente no sea capaz de reproducir archivos de audio, a pesar de que los formatos para ambos URIs sean similares. Especificando el tipo MIME de los datos enlazados, ayudamos al sistema Android para que localice la aplicación más adecuada para realizar la acción solicitada.

    A veces, el tipo MIME de los datos enlazados se puede deducir a través de su URI, particularmente cuando el URI es del tipo content:, es decir, que los datos cuentan con su propio proveedor de contenido ContentProvider. En este caso, el sistema será conocedor del tipo MIME asociado al proveedor.

    Para asignar solo el URI, usaremos el método setData(). Para asignar solo el tipo MIME usaremos el método setType(). Puedes utilizar el método setDataAndType() para asignar ambos valores.

  • Categoría.

    Se trata de una cadena informando sobre el tipo de componente que debería gestionar la intención. Puedes asociar más de una categoría a la intención. La mayoría de las intenciones no necesitan de una categoría.

    Algunas de las categorías más utilizadas:
    • CATEGORY_BROWSABLE. Indica que la actividad podrá ser iniciada desde un navegador cuando éste tenga que visualizar contenido enlazado como una imagen, o un mensaje de correo.
    • CATEGORY_LAUNCHER. Una actividad que tenga esta categoría asociada, significa que será la actividad que se inicie cuando la aplicación sea ejecutada.

    Para asignar una categoría utiliza el método addCategory().

  • Extras.

    Pares clave-valor que almacenan información extra para realizar la acción. Podemos añadir datos extra llamando al método putExtra(), que toma dos valores como argumentos: el nombre de una clave y su valor. Puedes también crear una instancia de la clase Bundle con todos los datos necesarios y volcarlos a la intención utilizando el método putExtras().

    Por ejemplo, cuando enviamos un correo electrónico especificando como acción ACTION_SEND, podemos especificar el destinatario del mensaje utilizando la clave EXTRA_EMAIL, y especificando el asunto del mensaje con la clave EXTRA_SUBJECT.

    Puedes definir tus propios claves para el envío de datos extra. Es recomendable usar el nombre del paquete de la aplicación como prefijo para evitar colisiones. Por ejemplo:
    static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
    
  • Indicadores.

    Los indicadores funcionan a modo de metadatos para la intención. Los indicadores sirven para decirle al sistema Android cómo lanzar una actividad (por ejemplo, a qué tarea pertenece la actividad) y a cómo tratarla después de haberla lanzado (por ejemplo, si pertenece al listado de actividades recientes).

    Para especificar un indicador concreto, usaremos el método setFlags().

Observa que de las propiedades anteriores, nombre del componente, acción, datos y categoría, sirven para que el sistema pueda identificar el componente al que va dirigida la intención. Los datos extra y los indicadores no sirven para identificar el componente destino, pero almacenan información adicional.

Ejemplo de intención explícita.

Para crear una intención explícita, todo lo que necesitamos es el nombre del componente de destino. El resto de propiedades son opcionales.

Por ejemplo, si contamos con un servicio en nuestra aplicación cuyo nombre de clase es DownloadService y que sirve para descargar un archivo desde el Web, puedes iniciar dicho servicio de la siguiente manera:
// Ejecutado en una actividad, 'this' hace referencia al contexto
// fileUrl es una cadena con la URL al archivo: "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

El constructor Intent(Context, Class) tiene dos parámetros: el contexto de la aplicación (Context) y un objeto de la propia clase del componente (instancia de la clase Class).

Ejemplo de una intención implícita.

Una intención implícita basa su funcionamiento en la especificación de una acción que tendrá que ser realizada por algún componente de alguna aplicación de nuestro dispositivo. Usar este tipo de intenciones es útil cuando nuestra aplicación no es capaz de realizar una acción determina que quizás otras si puedan.

Por ejemplo, si cuentas con contenido que quieres que el usuario pueda compartir con otros usuarios, podemos crear una intención asignándole la acción ACTION_SEND y añadiendo como datos extra el contenido que se desea compartir. Cuando llamamos al método startActivity() con esa intención, el usuario podrá seleccionar una aplicación a través de la cual podrá compartir el contenido.

Importante. Es posible que el usuario no disponga de la aplicación necesaria para realizar la acción especificada en la intención. En este caso, la llamada a startActivity() fallará y la aplicación fallará. Para evitar esto, usaremos el método resolveActivity() de nuestra intención. Si el resultado no es null, entonces existe al menos una aplicación que puede realizar la acción solicitada y podremos llamar al método startActivity() con la seguridad de que no va a fallar.

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // tipo MIME "text/plain"

// Comprobamos si existe alguna aplicación que cumpla con la intención
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

Nota. En este caso no se utiliza un URI, pero se utiliza la información extra de la intención para compartir una cadena de texto. Observa que además se indica que el tipo MIME del texto compartido es de tipo "text/plain" (texto plano).

Cuando llamamos al método startActivity(), el sistema localiza todas las aplicaciones que pueden gestionar este tipo de intención (una intención con la acción ACTION_SEND y que transporta datos de tipo MIME texto plano). Si existe solo una aplicación, ésta se ejecutará inmediatamente. Si existen varias aplicaciones, el sistema mostrará un cuadro de diálogo con todas ellas, dejando en manos del usuario la posibilidad de elegir una.

Forzando la selección de aplicaciones

Cuando hay más de una aplicación que responde a nuestra intención implícita, el usuario puede seleccionar qué aplicación usar y hacer que ésta sea la opción por defecto para la acción. Esto es lo correcto si se trata de una acción para que el usuario probablemente quiera usar la misma aplicación para abrir por ejemplo las páginas web desde sus navegador favorito.

Sin embargo, si existen varias aplicaciones que puedan responder a una intención y el usuario quiera usar una aplicación diferente cada vez, deberíamos plantearnos mostrar selector de aplicaciones siempre. Por ejemplo, cuando nuestra aplicación comparte información usando la acción ACTION_SEND. En este caso, el usuario querrá compartir la información a través de aplicaciones diferentes, dependiendo de las circunstancias. En este caso, tendremos que usar siempre el selector de aplicaciones (ver imagen 2).

Selector de aplicaciones.¡
Imagen 2. El selector de aplicaciones.

Para mostrar siempre el selector, usaremos la intención devuelta por el método estático createChooser() como argumento del método startActivity().
String titleChooser = getResources().getString(R.string.chooser_title);
Intent intent = Intent.createChooser(new Intent(Intent.ACTION_SEND), titleChooser);
startActivity(intent);

En este caso, si no existen aplicaciones en el sistema que cumplan con la intención, no se producirá un error y en su lugar, se mostrará el cuadro de diálogo con un mensaje de advertencia y con el título especificado en su cabecera.

Recibiendo una intención implícita.

Para publicar que un determinado componente de nuestra aplicación es capaz de tratar una intención implícita concreta, declaramos un nuevo elemento <intent-filter> en el archivo manifest. Por cada filtro de intenciones tendremos que especificar el tipo de intención que se acepta basándonos en la acción, los datos y la categoría. El sistema entregará la intención implícita al componente de nuestra aplicación, si la intención cumple alguno de sus filtros.

Nota. Una intención explícita siempre será entregada a su destinatario independientemente de si hay o no filtros de intención declarados.

Deberíamos declarar un filtro de intenciones por cada una de los trabajos que un componente sea capaz de hacer. Por ejemplo, una actividad en una aplicación galería de imágenes debería contar con dos filtros: un filtro para visualizar imágenes y otro filtro para editarlas. Cuando la actividad es iniciada, ésta analiza la información de la intención para saber si tiene o no que mostrar controles para la edición.

Cada filtro de intenciones será definido en el archivo manifest a través de un elemento <intent-filter> dentro de un componente de aplicación (un elemento <activity>, por ejemplo). Dentro del elemento <intent-filter> podremos especificar el tipo de intención a aceptar usando uno o más de los siguientes elementos:

  • <action>
    Declara la acción aceptada en el atributo name. El valor será un literal de cadena, no una constante de clase.
  • <data>
    Declara el tipo de datos aceptados, usando uno o más atributos que hacen referencia a varias características del URI de los datos (esquema, host, puerto, ruta, etc) y el tipo MIME.
  • <category>
  • Declara la categoría de la intención aceptada en un atributo name. El valor será un literal de cadena, no la constante de clase.

Nota. Para poder recibir intenciones implícitas, tendremos que declarar obligatoriamente la categoría CATEGORY_DEFAULT en el filtro de intenciones. Los métodos startActivity() y startActivityForResult() tratan a todas las intenciones como si pertenecieran a la categoría CATEGORY_DEFAULT. Si no declaras esta categoría en tu filtro de intenciones, la actividad nunca será iniciada por intenciones implícitas.

En el siguiente ejemplo podemos ver como una actividad declara su filtro de intenciones para recibir intenciones con cuya acción sea del tipo ACTION_SEND y datos del tipo texto:
<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>
Podríamos incluso utilizar más de un elemento <action>, <data>, o <category> Si lo haces, asegúrate de que el componente es capaz de gestionar cualquiera de las combinaciones de los elementos que hayas especificado.

Cuando queramos gestionar varios tipos de intenciones, pero para una combinación específica de acción, datos y categoría, entonces declararemos varios filtros.

Para que una intención pase un filtro que hayamos definido, tendrá que cumplir los requisitos impuestos en cada uno de los tres elementos: acción, datos y categoría. Si la intención no cumple alguno de los tres, no pasará el filtro y la intención no será entregada al componente. Si hubiera varios filtros de intenciones declarados, la intención sería entregada en el caso de que cumpliera con alguno de esos filtros.

Nota. Los filtros para una actividad tendrán que ser declarados en el archivo manifest. Sin embargo, los filtros para un receptor de avisos (BroadcastReceiver) puede ser registrado dinámicamente llamando al método registerReceiver(). Puedes eliminar el registro llamando al método unregisterReceiver(). Haciendo esto, podrás hacer que tu aplicación escuche avisos concretos durante el tiempo en el que la aplicación se esté ejecutando.

Usar filtros de intenciones no es una manera segura para evitar que otras aplicaciones puedan iniciar tus componentes. Aunque los filtros de intenciones restringen a que nuestro componente responda solo a un determinado tipo de intenciones implícitas, cualquier aplicación podría invocar el mismo componente a través de una intención explícita si un programador averigua el nombre de la clase del componente. Si necesitas que un componente determinado solo sea accesible desde tu propia aplicación, utiliza el atributo exported="false" para ese componente.

Un ejemplo.

El siguiente ejemplo hace referencia a compartir contenidos en redes sociales:

app/source/main/AndroidManifest.xml
<activity android:name="MainActivity">
    <!-- Actividad por defecto. Aparece en el lanzador de aplicaciones -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- Esta actividad gestioina acciones de tipo "SEND" con datos de tipo texto -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- Esta actividad también gestiona acciones de tipo "SEND" y "SEND_MULTIPLE" con datos de tipo multimedia -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

La primera actividad, MainActivity, es el punto de entrada principal de la aplicación, es decir, es la actividad que se iniciará cuando el usuario ejecute la aplicación desde el lanzador de aplicaciones:
  • ACTION_MAIN indica que se trata del punto de entrada principal.
  • Que no exista un elemento <data> significa que no se esperan datos asociados con la intención.
  • CATEGORY_LAUNCHER indica que el icono de la actividad aparecerá en el lanzador de aplicaciones. Si no se especifica un icono en el elemento <activity>, el sistema usará el icono asociado al elemento <application>

ACTION_MAIN y CATEGORY_LAUNCHER deben de declararse en conjunto para que la actividad aparezca en el lanzador de aplicaciones.

La segunda actividad, ShareActivity, se encargará de gestionar la compartición de texto y contenido multimedia. Aunque los usuarios podrán llegar a esta actividad a través de la interfaz asociada a MainActivity, también podrán llegar a ella desde cualquiera otra aplicación que emita una intención implícita cumpliendo con alguno de sus dos filtros.

Nota. El tipo MIME application/vnd.google.panorama360+jpg, es un tipo especial de datos para referirnos a fotos panorámicas. Este tipo de fotografías las podremos gestionar a través de la API Google panorama.

Usando intenciones pendientes.

Un objeto intención pendiente (PendingIntent) contiene una intención (Intent). Una aplicación creará una intención pendiente para ser enviada a otra aplicación. Con ello, la aplicación de destino podrá ejecutar la intención contenida con los mismos permisos de la aplicación que originó el envío.

Las intenciones pendientes se usan cuando:
  • Declarar una intención para ser ejecutada cuando el usuario realiza una acción sobre una notificación determinada. En este caso, es el gestor de notificaciones el que ejecuta la intención contenida.
  • Declarar una intención para ser ejecutada cuando el usuario realiza una acción desde un widget de aplicación. En este caso, es la aplicación que gestiona la pantalla de inicio la que ejecuta la intención contenida.
  • Declarar una intención para ser ejecutada con posterioridad. En este caso, será el gestor de alarmas del sistema el encargado de ejecutar la intención contenida.

Debido a que cada intención está diseñada para ser tratada por un tipo específico de componente (una actividad, un servicio o un receptor de avisos), tendremos que actuar de la misma manera a la hora de tratar con intenciones pendientes. Para crear una intención pendiente, utilizaremos los siguientes métodos:
  • PendingIntent.getActivity() para una intención que inicia una actividad.
  • PendingIntent.getService() para una intención que inicia un servicio.
  • PendingIntent.getBroadcast() para una intención que inicia un receptor de avisos.

A menos que nuestra aplicación reciba intenciones pendientes desde otras aplicaciones, los métodos anteriores serán los únicos que necesitaremos a la hora de crear intenciones pendientes.

Cada método toma como argumentos el contexto de la aplicación, la intención contenida y uno o más indicadores referentes a cómo debería ser usada la intención (por ejemplo, si la intención puede ser usada en más de una ocasión).

Resolución de intenciones.

Cuando el sistema recibe una intención implícita para iniciar cierta actividad, busca la mejor de las candidatas examinando sus filtros de intenciones basándose en tres factores:
  • La acción de la intención.
  • Los datos de la intención (tanto el URI, como el tipo de datos).
  • La categoría de la intención.

Comprobando la acción.

Para declarar que una actividad es capaz de aceptar intenciones implícitas asociadas a determinadas acciones, en su filtro de intenciones vamos a declarar tantos elementos <action> como sean necesarios. Por ejmplo:
<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

Para pasar el filtro, la acción asociada a la intención deberá coincidir con alguna de las acciones declaradas en el propio filtro.

Si el filtro no define acciones, ninguna intención podrá pasarlo. Por otro lado, si una intención no tiene una acción asociada, pasará el filtro siempre y cuando éste declare al menos una acción.

Comprobando la categoría.

Para especificar qué categorías son aceptadas por el filtro, tendremos que declarar uno o varios elementos <category>. Por ejemplo:
<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>
Para que una intención pase este filtro, cada una de las categorías definidas en la intención deberán estar declaradas por el filtro. Es decir, que el filtro puede contar con un número de categorías mayor al especificado por la intención y aún así, ésta pasará el filtro. Por otro lado, una intención sin categorías, siempre pasará el filtro independientemente de las categorías definidas por éste.

Nota. Android asigna por defecto la categoría CATEGORY_DEFAULT a todas las intenciones implícitas y pasadas como argumento a los métodos startActivity() y startActivityForResult(). Por ello, si quieres que una actividad reciba intenciones implícitas, ésta tendrá que declarar al menos dicha categoría en su filtro de intenciones (especificando como valor android.intent.category.DEFAULT, como en el ejemplo).

Comprobando los datos.

Para especificar qué tipo de datos son aceptados por el filtro, tendremos que declarar uno o varios elementos <data>. Por ejemplo:
<intent-filter>
    <data android:mimeType="video/mpeg" android:scheme="http" ... />
    <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    ...
</intent-filter>
Un elemento <data> puede especificar información referente a la estructura del URI y al tipo MIME de los datos. Para la estructura del URI, contamos con varios atributos: scheme, host, port y path. Cada uno de estos atributos, representa una parte del URI:

<scheme>://<host>:<port>/<path>

Por ejemplo:

content://com.example.project:200/folder/subfolder/etc

En el URI anterior, el esquema (scheme) es content, el anfitrión (host) es com.example.project, el puerto (port) es el 200 y la ruta (path) es folder/subfolder/etc.

Todos estos atributos son opcionales, pero tendremos que tener en cuenta las siguientes reglas para hacer un uso correcto de los mismos:
  • Si no se especifica el esquema, el anfitrión será ignorado.
  • Si no se especifica el anfitrión, el puerto será ignorado.
  • Si no se especifica ni el esquema ni el puerto, la ruta será ignorada.

Cuando el URI de una intención se compara con el URI especificado en el filtro, sólo se compara con las partes declaradas en el filtro. Por ejemplo:
  • Si el filtro especifica solo un esquema, los URIs que tengan el mismo esquema pasarán el filtro.
  • Si el filtro especifica solo un esquema y una autoridad (authority) pero no la ruta, los URIs que tengan el mismo esquema y autoridad pasarán el filtro independientemente de sus rutas.
  • Si el filtro especifica solo un esquema, una autoridad y una ruta, los URIs que tengan el mismo esquema, autoridad y ruta pasarán el filtro.

Nota. Una ruta puede contener el carácter comodín asterisco (*) para obligar a que solo una parte de la ruta sea coincidente.

La comprobación de los datos de la intención se hace tanto con el URI como el tipo MIME de los datos teniendo en cuenta que:
  • Una intención que no cuenta ni con un URI ni con un tipo MIME pasará el filtro si éste no define URIs o tipos MIME.
  • Una intención que cuente con un URI pero no con un tipo MIME (ni se puede deducir del URI, ni se proporciona de manera explícita) pasará el filtro si el URI coincide con el URI del filtro y éste no define un tipo MIME.
  • Una intención que cuente con un tipo MIME pero no con un URI pasará el filtro si el tipo MIME coincide con el tipo MIME del filtro y éste no define un URI.
  • Una intención que contenga tanto un URI como un tipo MIME (tanto si éste puede deducirse del URI como si se proporciona de manera explícita) pasará el filtro si: primero, el tipo MIME coincide con el tipo MIME del filtro y segundo, el URI coincide con el URI del filtro, o bien, si el URI cuenta con un esquema content: o file: y el filtro no define URI. Es decir, que un componente está hecho para poder dar soporte a datos cuyo esquema sea content: o file: aunque el filtro sólo defina sus tipos MIME.

No hay comentarios:

Publicar un comentario