domingo, marzo 20, 2016

Genexus PushNotificaction con el Generador de Java




Para superar algunos problemas con el proceso de notificar a los usuarios de Telefonos inteligentes, esecialmente en el caso del Generador Java de Genexus Evolution 3 Upgrade 5 o en adelante.


Se comparte la experiencia con breves anotaciones para poder avanzar en ese sentido y no tener los tipicos tropiezos que resulta al momento de utilizar e integrar plataformas diferentes, para el caso tomamos como referencia el SAC #36306, que nos ayuda mucho en resolver el problema, con sus respectivas sugerencias, recuerde que son dos momentos que se tienen que integrar DESDE EL DISPOSITIVO Y DESDE LA APLICACION WEB, ese uno se debe tener claro.


Configurar en Google Cloud Messaging

 SAC #36306: No se está enviando el parámetro Parameters del método CallActions de las Notifications Push
Sorry, no English translation available; Spanish version displayed.


Abstract
El método CallAction del objeto externo Notifications dispone de un parámetro llamado  Parameters, el cual es utiliza para enviar un dato como parámetro en la notificación.
Dicho parámetro configurado desde GeneXus no está siendo enviado al servicio de mensajería (de Google o Apple) que procesa la notificación.
Detailed description
Se tiene una app que recepta notificaciones. Se desea que al momento de recibir la notificación en el DISPOSITIVO, se ejecute un determinado SD Panel, con un o mas parámetros. Citemeos un ejemplo, al enviar la notificación sobre determinada oferta de producto, abrir directamente una VISTA de ese producto.

El método CallActions del objeto Notifications permite configurar el evento que seria ejecutado en el DISPOSITIVO, cuando este se recibe la notificación y uno o mas parámetros.

El problema es que dicho parámetro &Parameters no está siendo considerado al momento de invocar el servicio de mensajería.

Ejemplo:
Supongamos que nuestra app tiene un SD Panel llamado "SDPanel1" , y en el mismo se define el evento "Ver_Cliente" , para invocar al Ver  cliente con el parámetro recibido en la notificación.

Event 'Ver_Cliente'
       Composite
           &ClienteId = &PARAMETRO.Trim().ToNumeric()
           WorkWithDevicesCliente.Cliente.Detail(&ClienteId)
       Endcomposite
Endevent

Siendo este el código del objeto Web que dispara la notificación desde el server:

&NotificationParameters.SetParameter('PARAMETRO', &ClienteId.ToString())
for each //para todos los Dispositivos
       &Notifications.CallAction('SDPanel1',DeviceType,DeviceToken,&message, 'Ver_Cliente', &NotificationParameters)
endfor

Siendo:
- 'SDPanel1' el main SD que recibe la notificación
- &message el mensaje a recibir en la notificación
- 'Ver_Cliente' el evento definido en SDPanel1, que debe ejecutarse al receptar la notificación.

El problema es que el parámetro &NotificationParameters no está siendo considerado en la llamada al servicio.
Por lo tanto la app si bien recibe la notificación y ejecuta el evento correspondiente (Ver_Cliente), no recibe el parámetro en la variable &PARAMETRO.

Work around
Hay dos alternativas :
1. Utilizar el método SEND. El método Add/Send es otra opcion para enviar todos los mensajes a la vez al servicio de mensajeria. El SDT RemoteNotification de dicho método también tiene la posibilidad de configurar parámetros y en ese caso funciona.
Importante: Este método no esta disponible para todos los generadores. Por más info ver URL de Referencia

2. Para el caso de Android , en lugar de utilizar el método CallAction que dispone Genexus, realizar el POST al servicio de Google en forma manual, con HttpClient, de tal manera que resulte el envio del parámetro adicional.

El codigo para invocar al servicio rest, lo describimos a continuacion:

For each
&HttpClient.Host = 'android.googleapis.com'
&HttpClient.BaseUrl = '/gcm/'
&HttpClient.AddHeader(!'Authorization', !'Key=<ANDROID SENDER API KEY>') //Es el valor de la prop con ese nombre en el main SD.
&HttpClient.AddHeader(!'Content-Type', !'application/x-www-form-urlencoded;charset=UTF-8')

&Msg = 'registration_id='+ DeviceToken +'&collapse_key=0&data.payload='+ &message +'&data.action=Ver_Cliente&data.parameters=[{"PARAMETRO":"'+&ClienteId.ToString()+'"}]'


En resumen es una trama JSON.

&HttpClient.AddString(&Msg)
&HttpClient.Execute(!'POST',!'send')
Endfor

________________________________________________________________________________
________________________________________________________________________________

En el siguiente SAC hace referencia a este problema que lo identificamos para dar solución, a continuacion transcribimos el contenido del sac y sus comentarios.
SAC #36306: No se está enviando el parámetro Parameters del método CallActions de las Notifications Push


Abstract
El método CallAction del objeto externo Notifications dispone de un parámetro Parameters, el cual se utiliza para enviar un parámetro en la notificación.
Ese parámetro configurado desde GeneXus no está siendo enviado al servicio de mensajería (de Google o Apple) que procesa la notificación.

Detailed description
Se tiene una app que recibe notificaciones. Se desea que al momento de recibir la notificación en el device, se ejecute un determinado SD Panel, con un cierto parámetro. Por ejemplo, al enviar la notificación sobre determinada oferta de producto, abrir directamente el View de ese producto.

El método CallActions del objeto Notifications permite configurar el evento a ser disparado en el device cuando se recibe la notificación y un parámetro para el mismo.

El problema es que ese parámetro &Parameters no está siendo considerado al momento de invocar el servicio de mensajería.

Ejemplo:
Supongamos que nuestra app tiene un SD Panel llamado "SDPanel1" , y en el mismo se define el evento "Ver_Cliente" , para invocar al View del cliente con el parámetro recibido en la notificación.

Event 'Ver_Cliente'
      Composite
          &ClienteId = &PARAMETRO.Trim().ToNumeric()
          WorkWithDevicesCliente.Cliente.Detail(&ClienteId)
      Endcomposite
Endevent


Y este es el código del objeto Web que dispara la notificación desde el server:

&NotificationParameters.SetParameter('PARAMETRO', &ClienteId.ToString())
for each //para todos los devices
&Notifications.CallAction('SDPanel1',DeviceType,DeviceToken,&message, 'Ver_Cliente', &NotificationParameters)
endfor

Siendo:
- 'SDPanel1' el main SD que recibe la notificación
- &message el mensaje a recibir en la notificación
- 'Ver_Cliente' el evento definido en SDPanel1, que debe ejecutarse al ver la notificación.

El problema es que el parámetro &NotificationParameters no está siendo considerado en la llamada al servicio.
Por lo tanto la app si bien recibe la notificación y ejecuta el evento correspondiente (Ver_Cliente), no recibe el parámetro en la variable &PARAMETRO.

Work around
Hay dos alternativas :
1. Utilizar el método SEND. El método Add/Send es otra opcion para enviar todos los mensajes a la vez al servicio de mensajeria. El SDT RemoteNotification de dicho método también tiene la posibilidad de configurar parámetros y en ese caso funciona.
Importante: Este método no esta disponible para todos los generadores. Por más info ver http://wiki.genexus.com/commwiki/servlet/hwikibypageid?18150

2. Para el caso de Android , en lugar de utilizar el método CallAction que dispone Genexus, realizar el POST al servicio de Google en forma manual, con HttpClient, de forma tal de poder enviar ese parámetro adicional.

El codigo para invocar el servicio rest, siguiendo el ejemplo anterior, sería así:

For each 
    Where DeviceId = &DeviceId
&HttpClient.Host = 'android.googleapis.com'
&HttpClient.BaseUrl = '/gcm/'
&HttpClient.AddHeader(!'Authorization', !'Key=<ANDROID SENDER API KEY>') //Es el valor de la prop con ese nombre en el main SD.
&HttpClient.AddHeader(!'Content-Type', !'application/x-www-form-urlencoded;charset=UTF-8')

&Msg = 'registration_id='+ DeviceToken +'&collapse_key=0&data.payload='+ &message +'&data.action=Ver_Cliente&data.parameters=[{"PARAMETRO":"'+&ClienteId.ToString()+'"}]'

&HttpClient.AddString(&Msg)
&HttpClient.Execute(!'POST',!'send')

    if &HttpClient.ErrCode <> 0
        msg(&HttpClient.ErrDescription)
    else
        msg('Notificación Enviada Exitosamente')
    endif
When none
    msg('No se Encontro Dispositivo !!')
Endfor


Referencias:
Informacion para configurar un Ambiente
PUSH Notificaciones
   Configurando Push Notifications en Android Applications,
    Configuriando Google Cloud Messaging for Android,

viernes, marzo 18, 2016

Generar web.xml desde el mismo Genexus








&Directorio.Source = 'C:\Tomcat7webapps\miaplicacion\WEB-INF\classes'
msg('Directorio '  + &Directorio)
if &Directorio.exists() 
    msg("Este directorio si EXISTE!")
else
    msg("ESTE DIRECTORIO NO EXISTE !")
endif

&i = dfwopen("miweb.xml"," ",'')
&i = dfwptxt("----------------")
&i = dfwnext()

for &auxFile in &directorio.GetFiles('class')
&i = dfwptxt("<servlet>")
&i = dfwnext()
&pos = StrSearch(&auxFile.GetName(),'.class',1)
&pos = &pos - 1
&cadena = Substr(&auxFile.GetName(),1,&pos)
&cadena = "<servlet-name>" + trim(&cadena) + "</servlet-name>"
&i = dfwptxt(&cadena.Trim())
&i = dfwnext()
&cadena = Substr(&auxFile.GetName(),1,&pos)
&cadena = "<servlet-class>" + trim(&cadena ) + "</servlet-class>"
&i = dfwptxt(&cadena.Trim())
&i = dfwnext()
&i = dfwptxt("</servlet>")
&i = dfwnext()
endfor


&i = dfwptxt("----------------")
&i = dfwnext()

for &auxFile in &directorio.GetFiles('class')
&i = dfwptxt("<servlet-mapping>")
&i = dfwnext()
&pos = StrSearch(&auxFile.GetName(),'.class',1)
&pos = &pos - 1
&cadena = Substr(&auxFile.GetName(),1,&pos)

&cadena = "<servlet-name>" + trim(&cadena ) + "</servlet-name>"
&i = dfwptxt(&cadena.Trim() )
&i = dfwnext()
&cadena = Substr(&auxFile.GetName(),1,&pos)
&cadena = "<url-pattern>/servlet/" + trim(&cadena ) + "</url-pattern>"
&i = dfwptxt(&cadena.Trim() )
&i = dfwnext()
&i = dfwptxt("</servlet-mapping>")
&i = dfwnext()
endfor

    &i = dfwclose()           

Return