WillyWeb
07/07/16, 18:20:01
En más de una ocasión he usado la variable interna %caller1 para dar respuesta/solución a alguna consulta. Por ejemplo en estos temas...
http://www.htcmania.com/showthread.php?p=18925847#post18925847
http://www.htcmania.com/showthread.php?p=20043474#post20043474
http://www.htcmania.com/showthread.php?p=22171901#post22171901
... y en el más reciente ...
http://www.htcmania.com/showthread.php?p=23624241#post23624241
Viendo que esa variable %caller1 tiene una gran utilidad Caravantes me invitó (http://www.htcmania.com/showthread.php?p=23633576#post23633576) a explicar su uso con un poco más de detalle ... esto es lo que me ha salido. :silbando:
Tipos de variables
La documentación de Tasker organiza las variables dependiendo de su ámbito o de quién les asigna su valor.
Por su ámbito pueden ser globales y locales.
Por quien les asigna valor pueden ser internas y de usuario.
Los detalles se pueden consultar aquí: http://tasker.dinglisch.net/userguide/en/variables.html
Combinando esas cuatro posibilidades obtenemos los tipos de variables más habituales:
Las variables “globales internas”. Son las que usamos para conocer el nivel de batería (%BATT), la fecha (%DATE) o las coordenadas GPS (%LOC). Tasker tiene un amplio catálogo de estas variables.
Las variables “globales de usuario”. Son las que usamos en nuestros desarrollos si queremos conservar su valor por tiempo indefinido o si lo queremos consultar/modificar desde varias tareas/escenas.
Las variables “locales de usuario”. Son las que usamos en nuestros desarrollos si queremos que su ámbito se limite a la tarea/escena en la que son creadas.
Existe un tipo más, el de las variables “locales internas”, que nos proporcionan información extra sobre la tarea en la que son consultadas.
Información de error: %err y %errmsg
Prioridad de la tarea: %priority
Tiempo que la tarea lleva funcionando: %qtime
Quién ha iniciado la tarea: %caller (realmente es un array)
Es precisamente sobre esta última variable, el array %caller, sobre lo que trata este pequeño tutorial.
El array %caller
El array %caller permite trazar cómo ha llegado a iniciarse la tarea/escena actual.
Supongamos que tenemos un perfil “P” que al activarse lanza la tarea “T1” que muestra la escena “E” que tiene un botón “B” que lanza la tarea “T2”. Si desde la tarea “T2” consultamos cada elemento del array %caller podremos seguir toda la secuencia:
%caller1 contendrá “botón B de la escena E”
%caller2 contendrá “tarea T1”
%caller3 contendrá “entrada del perfil P
El formato de cada elemento del array %caller no es exactamente el que he puesto en el ejemplo anterior, realmente es así: callertype(=callername(:subcallername))
La parte callertype aparece siempre y las otras dos (callername y subcallername) dependiendo de las circunstancias.
Los posibles callertype se detallan a continuación:
profile
Si la tarea se inicia desde un perfil en callername pondrá enter o exit dependiendo de si el perfil se ha activado o desactivado. En subcallername pondrá el nombre del perfil y si no tiene nombre pondrá anon.
Ejemplos:
profile=enter:MiPerfil ... al activarse el perfil MiPerfil
profile=exit:MiPerfil ... al desactivarse el perfil MiPerfil
scene
Si la tarea se inicia desde una escena en callername pondrá el nombre de la escena. Si el evento que lanza la tarea se genera desde un elemento en subcallername pondrá el nombre del elemento. Si el evento se genera al pulsar sobre una opción de la barra de acciones en subcallername pondrá la etiqueta de la acción, si la tiene asignada. Para eventos globales de la escena en subcallername pondrá el tipo de evento.
Ejemplos:
scene=MiEscena:MiBotón ... al pulsar el botón MiBotón de la escena MiEscena
scene=MiEscena:MiAcción ... al pulsar la acción con etiqueta MiAcción de la escena MiEscena
scene=MiEscena:Key ... al salir de la escena MiEscena pulsando el botón Back de Android
ui
Si la tarea se inicia al pulsar el botón PLAY en el editor de tareas.
launch
Si la tarea es exportada como aplicación y se inicia desde el lanzador de aplicaciones del sistema.
notification
Si la tarea se inicia desde un botón de acción de una notificación.
external
Si la tarea se inicia desde una aplicación externa. Por ejemplo; un widget de Zoom.
task
Si la tarea se inicia desde otra tarea usando la acción “Realizar tarea” en subcallername pondrá el nombre de esa tarea y si no tiene nombre pondrá anon.
Ejemplo:
task=MiTarea ... si la tarea ha sido lanzada desde MiTarea
¿Qué utilidad tiene todo esto?
La mejor que yo he encontrado es la de poder usar una única tarea para la entrada y la salida de un perfil. Esto es de especial utilidad si una de las tareas tiene que interrumpir la ejecución de la otra.
Supongamos que quieres montar un sistema que encienda el WiFi al iniciar ciertas aplicaciones y que lo apague al cerrarlas, pero para evitar apagados/encendidos innecesarios se te ha ocurrido que puedes esperar unos segundos antes de apagar el WiFi por si abres a continuación otra de las aplicaciones controladas por este sistema.
La forma más simple de hacerlo tendría este aspecto:
Perfil: EstadoApp (11)
Aplicación: YouTube o Google
Entrada: WiFiOn (22)
A1: Flash [ Texto:%priority | %caller1 Largo:Encendido ]
A2: Detener [ Con error:Apagado Tarea:WiFiOff ]
A3: WiFi [ Establecer:Encendido ]
Salida: WiFiOff (33)
A1: Flash [ Texto:%priority | %caller1 Largo:Encendido ]
A2: Esperar [ MS:0 Segundos:10 Minutos:0 Horas:0 Días:0 ]
A3: WiFi [ Establecer:Apagado ]
Pero esto, que en principio debería funcionar, no funciona como esperabas. La tarea de salida no se para y siempre se te apaga el WiFi aunque abras otra de las aplicaciones controladas antes de que termine esa espera de 10 segundos … ¿qué está pasando aquí? :loco:
Pues que la acción “Detener” no se ejecuta a tiempo porque la tarea WiFiOn no se inicia hasta que termina la tarea WiFiOff. Es una cuestión de prioridades (%priority) y de la forma en la que funciona Tasker.
Para entender esto tienes que tener en cuenta estas cosas:
Las acciones de las tareas con prioridad más alta se ejecutan antes que las acciones de las que tienen prioridad más baja.
Las acciones “Esperar” y “Esperar hasta” son casos especiales que no siempre siguen esa regla de la prioridad. Tasker las gestiona lo mejor que puede en cada circunstancia.
De forma predeterminada las tareas iniciadas por la entrada de un perfil tienen prioridad 5 y las iniciadas por la salida tienen prioridad 1006.
Los detalles se pueden consultar aquí: http://tasker.dinglisch.net/userguide/en/tasks.html
Con eso en mente no es difícil ver que estás intentando detener una tarea con prioridad 1006 desde otra tarea, que por tener prioridad 5, probablemente no se ejecutará hasta que termine la que pretendes detener, porque casualmente está en una espera.
Una forma de solucionar esta situación, para mi gusto la más elegante, es usar el “Manejo de incompatibilidades” para permitir que la segunda ejecución de una tarea interrumpa a la primera, y usar el array %caller para saber si una tarea se está ejecutando como consecuencia de la entrada o de la salida de un perfil.
El sistema del ejemplo anterior quedaría así:
Perfil: EstadoApp (11)
Aplicación: YouTube o Google
Entrada y Salida: WiFiOnOff (44)
Abortar Tarea Existente
A1: Flash [ Texto:%priority | %caller1 Largo:Encendido ]
A2: Si (if) [ %caller1 ~ *enter* ]
A3: WiFi [ Establecer:Encendido ]
A4: Else
A5: Esperar [ MS:0 Segundos:10 Minutos:0 Horas:0 Días:0 ]
A6: WiFi [ Establecer:Apagado ]
A7: Fin si (End if)
¿Y sólo vale para esto?
Ni mucho menos. Sólo tienes que dar un vistazo a los temas que he puesto al principio. ;-)
Otro posible escenario en el que hacer uso del array %caller podría estar formado por una escena con varios botones que lanzasen la misma tarea. Consultando el valor de %caller1 esa tarea podía saber desde qué botón de la escena ha sido lanzada y actuar en consecuencia.
Hasta la próxima :cucu:
http://www.htcmania.com/showthread.php?p=18925847#post18925847
http://www.htcmania.com/showthread.php?p=20043474#post20043474
http://www.htcmania.com/showthread.php?p=22171901#post22171901
... y en el más reciente ...
http://www.htcmania.com/showthread.php?p=23624241#post23624241
Viendo que esa variable %caller1 tiene una gran utilidad Caravantes me invitó (http://www.htcmania.com/showthread.php?p=23633576#post23633576) a explicar su uso con un poco más de detalle ... esto es lo que me ha salido. :silbando:
Tipos de variables
La documentación de Tasker organiza las variables dependiendo de su ámbito o de quién les asigna su valor.
Por su ámbito pueden ser globales y locales.
Por quien les asigna valor pueden ser internas y de usuario.
Los detalles se pueden consultar aquí: http://tasker.dinglisch.net/userguide/en/variables.html
Combinando esas cuatro posibilidades obtenemos los tipos de variables más habituales:
Las variables “globales internas”. Son las que usamos para conocer el nivel de batería (%BATT), la fecha (%DATE) o las coordenadas GPS (%LOC). Tasker tiene un amplio catálogo de estas variables.
Las variables “globales de usuario”. Son las que usamos en nuestros desarrollos si queremos conservar su valor por tiempo indefinido o si lo queremos consultar/modificar desde varias tareas/escenas.
Las variables “locales de usuario”. Son las que usamos en nuestros desarrollos si queremos que su ámbito se limite a la tarea/escena en la que son creadas.
Existe un tipo más, el de las variables “locales internas”, que nos proporcionan información extra sobre la tarea en la que son consultadas.
Información de error: %err y %errmsg
Prioridad de la tarea: %priority
Tiempo que la tarea lleva funcionando: %qtime
Quién ha iniciado la tarea: %caller (realmente es un array)
Es precisamente sobre esta última variable, el array %caller, sobre lo que trata este pequeño tutorial.
El array %caller
El array %caller permite trazar cómo ha llegado a iniciarse la tarea/escena actual.
Supongamos que tenemos un perfil “P” que al activarse lanza la tarea “T1” que muestra la escena “E” que tiene un botón “B” que lanza la tarea “T2”. Si desde la tarea “T2” consultamos cada elemento del array %caller podremos seguir toda la secuencia:
%caller1 contendrá “botón B de la escena E”
%caller2 contendrá “tarea T1”
%caller3 contendrá “entrada del perfil P
El formato de cada elemento del array %caller no es exactamente el que he puesto en el ejemplo anterior, realmente es así: callertype(=callername(:subcallername))
La parte callertype aparece siempre y las otras dos (callername y subcallername) dependiendo de las circunstancias.
Los posibles callertype se detallan a continuación:
profile
Si la tarea se inicia desde un perfil en callername pondrá enter o exit dependiendo de si el perfil se ha activado o desactivado. En subcallername pondrá el nombre del perfil y si no tiene nombre pondrá anon.
Ejemplos:
profile=enter:MiPerfil ... al activarse el perfil MiPerfil
profile=exit:MiPerfil ... al desactivarse el perfil MiPerfil
scene
Si la tarea se inicia desde una escena en callername pondrá el nombre de la escena. Si el evento que lanza la tarea se genera desde un elemento en subcallername pondrá el nombre del elemento. Si el evento se genera al pulsar sobre una opción de la barra de acciones en subcallername pondrá la etiqueta de la acción, si la tiene asignada. Para eventos globales de la escena en subcallername pondrá el tipo de evento.
Ejemplos:
scene=MiEscena:MiBotón ... al pulsar el botón MiBotón de la escena MiEscena
scene=MiEscena:MiAcción ... al pulsar la acción con etiqueta MiAcción de la escena MiEscena
scene=MiEscena:Key ... al salir de la escena MiEscena pulsando el botón Back de Android
ui
Si la tarea se inicia al pulsar el botón PLAY en el editor de tareas.
launch
Si la tarea es exportada como aplicación y se inicia desde el lanzador de aplicaciones del sistema.
notification
Si la tarea se inicia desde un botón de acción de una notificación.
external
Si la tarea se inicia desde una aplicación externa. Por ejemplo; un widget de Zoom.
task
Si la tarea se inicia desde otra tarea usando la acción “Realizar tarea” en subcallername pondrá el nombre de esa tarea y si no tiene nombre pondrá anon.
Ejemplo:
task=MiTarea ... si la tarea ha sido lanzada desde MiTarea
¿Qué utilidad tiene todo esto?
La mejor que yo he encontrado es la de poder usar una única tarea para la entrada y la salida de un perfil. Esto es de especial utilidad si una de las tareas tiene que interrumpir la ejecución de la otra.
Supongamos que quieres montar un sistema que encienda el WiFi al iniciar ciertas aplicaciones y que lo apague al cerrarlas, pero para evitar apagados/encendidos innecesarios se te ha ocurrido que puedes esperar unos segundos antes de apagar el WiFi por si abres a continuación otra de las aplicaciones controladas por este sistema.
La forma más simple de hacerlo tendría este aspecto:
Perfil: EstadoApp (11)
Aplicación: YouTube o Google
Entrada: WiFiOn (22)
A1: Flash [ Texto:%priority | %caller1 Largo:Encendido ]
A2: Detener [ Con error:Apagado Tarea:WiFiOff ]
A3: WiFi [ Establecer:Encendido ]
Salida: WiFiOff (33)
A1: Flash [ Texto:%priority | %caller1 Largo:Encendido ]
A2: Esperar [ MS:0 Segundos:10 Minutos:0 Horas:0 Días:0 ]
A3: WiFi [ Establecer:Apagado ]
Pero esto, que en principio debería funcionar, no funciona como esperabas. La tarea de salida no se para y siempre se te apaga el WiFi aunque abras otra de las aplicaciones controladas antes de que termine esa espera de 10 segundos … ¿qué está pasando aquí? :loco:
Pues que la acción “Detener” no se ejecuta a tiempo porque la tarea WiFiOn no se inicia hasta que termina la tarea WiFiOff. Es una cuestión de prioridades (%priority) y de la forma en la que funciona Tasker.
Para entender esto tienes que tener en cuenta estas cosas:
Las acciones de las tareas con prioridad más alta se ejecutan antes que las acciones de las que tienen prioridad más baja.
Las acciones “Esperar” y “Esperar hasta” son casos especiales que no siempre siguen esa regla de la prioridad. Tasker las gestiona lo mejor que puede en cada circunstancia.
De forma predeterminada las tareas iniciadas por la entrada de un perfil tienen prioridad 5 y las iniciadas por la salida tienen prioridad 1006.
Los detalles se pueden consultar aquí: http://tasker.dinglisch.net/userguide/en/tasks.html
Con eso en mente no es difícil ver que estás intentando detener una tarea con prioridad 1006 desde otra tarea, que por tener prioridad 5, probablemente no se ejecutará hasta que termine la que pretendes detener, porque casualmente está en una espera.
Una forma de solucionar esta situación, para mi gusto la más elegante, es usar el “Manejo de incompatibilidades” para permitir que la segunda ejecución de una tarea interrumpa a la primera, y usar el array %caller para saber si una tarea se está ejecutando como consecuencia de la entrada o de la salida de un perfil.
El sistema del ejemplo anterior quedaría así:
Perfil: EstadoApp (11)
Aplicación: YouTube o Google
Entrada y Salida: WiFiOnOff (44)
Abortar Tarea Existente
A1: Flash [ Texto:%priority | %caller1 Largo:Encendido ]
A2: Si (if) [ %caller1 ~ *enter* ]
A3: WiFi [ Establecer:Encendido ]
A4: Else
A5: Esperar [ MS:0 Segundos:10 Minutos:0 Horas:0 Días:0 ]
A6: WiFi [ Establecer:Apagado ]
A7: Fin si (End if)
¿Y sólo vale para esto?
Ni mucho menos. Sólo tienes que dar un vistazo a los temas que he puesto al principio. ;-)
Otro posible escenario en el que hacer uso del array %caller podría estar formado por una escena con varios botones que lanzasen la misma tarea. Consultando el valor de %caller1 esa tarea podía saber desde qué botón de la escena ha sido lanzada y actuar en consecuencia.
Hasta la próxima :cucu: