Spanish [SOLUCIONADO] Problema al pulsar el icono de notificación trabajando con Firebase Notifications

Seneca

Active Member
Licensed User
Hola.

Estoy trabajando con Firebase Notifications, usando el siguiente código para recibir y alertar de un mensaje mediante un icono en la barra de notificaciones.

B4X:
Sub fm_MessageArrived (Message As RemoteMessage)
    Log("Message arrived")
    Log($"Message data: ${Message.GetData}"$)
    Dim n As Notification
    n.Initialize
    n.Icon = "icon"
    n.SetInfo2(Message.GetData.Get("title"), Message.GetData.Get("body"), Message.GetData.Get("body"), "main")
    n.Notify(1)
End Sub

No quiero que el mensaje recibido se muestre en pantalla hasta que el usuario despliegue la barra de notificaciones y pulse sobre el icono de la notificación recibida. Y aquí es donde me surge la duda.

  • Si la app está en la actividad Main, al pulsar el icono de la notificación se me ejecuta la Sub Activity_Resume (dentro Main). Aquí compruebo que se ha pulsado en el icono de la notificación y, en ese caso, la muestro en pantalla con un Msgbox. Todo esto, correcto. Lo hago con este código:
    B4X:
    Dim in As Intent
    in = Activity.GetStartingIntent
    If in.HasExtra("Notification_Tag") Then
        LogColor (in.GetExtra("Notification_Tag"),Colors.Yellow) 'Will log the tag
        Msgbox(in.GetExtra("Notification_Tag"),"Notificación")
    End If
  • Sin embargo, si la app está en cualquier actividad distinta a Main, al pulsar el icono de la notificación se me ejecuta la Sub Activity_Create (dentro de Main) de forma que la actividad que había en pantalla es sustituida por esta, por Main.
Y este segundo caso es el que quiero evitar. Lo que busco es que la Actividad que haya en pantalla permanezca ahí (y no se sustituya por Main) cuando se pulsa el icono de la notificación, y que superpuesto se me muestre un Msgbox con la notificación.

¿Alguna orientación de cómo conseguirlo?

Gracias.
 
Last edited:

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Séneca:

En el Resume haz que cuando te llegue la notificacion llamar al activity que te interese con StartActivity(nombre activity) . No se si es la solución mas elegante, pero es lo que hago yo :D

Saludos
 

Seneca

Active Member
Licensed User
Hola.

En realidad lo que busco, que quizás no pueda hacerse, es que no se cargue una nueva actividad, sino que sobre la que esté en pantalla en el momento de pulsar sobre el icono de notificación se superponga un Msgbox.

Para el caso que me indicas de querer cargar una actividad, creo que puede indicarse directamente en el último parámetro de n.SetInfo2 sin tener que pasar por el Main.Resume

B4X:
   n.SetInfo2(Message.GetData.Get("title"), Message.GetData.Get("body"), Message.GetData.Get("body"), "Acitivity_a_cargar")

Saludos.
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola, creo que es facil, creas un formulario donde recibes las notificaciones, en el
SetInfo2 en vez de main pones el nombre de ese formulario, y cuando la recibas irá allí, pones el msgbox y cuando lo acepten cierras el formulario y volverá al que estabas.

Y si quieres rizar el rizo, ese formulario que recibe las notificaciones hazlo transparente ;)

Saludos
 

Seneca

Active Member
Licensed User
Hola.

¿Cuando indicas Formulario entiendo que te refieres a una nueva Actividad?

Saludos.
 

Seneca

Active Member
Licensed User
Hola.

Lo he probado y al cargar el nuevo Activity que me muestra el Msgbox, desplaza hacia la izquierda el Activity que había en pantalla hasta ese momento. Y esto es así aunque al nuevo Activity le ponga el fondo transparente.

Saludos.
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola

A mi no me lo hizo, quizas dependa de la versión de android que utilices en el dispositivo o en el sdk.
Si no te gusta como queda, igual tendrias que crearte una seudonotificacion propia, y como eres tu el que pones la notificación, poner esa desde donde te interese sacando solo el msgbox o incluso un panel con una etiqueta y un boton de aceptar, esto va a gustos y dependiendo de la aplicacion

Saludos
 

Seneca

Active Member
Licensed User
Hola.

Lo primero, agradecerte @bgsoft todo el interés en encontrar una solución. Quería preguntarte ¿a qué te refieres con"seudonotificación"?

Gracias.
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Seneca, aqui estamos para ayudarnos, asi que no hay nada que agradecer.

Tu con el n.Notify(1) estás lanzando una notificación al usuario, por lo tanto la generas tu, no otra aplicación, asi que sabes cuando tienes que notificar y quieres enseñarle un msgbox, si en vez de lanzar una notificación pones un panel, que suba por encima de todo y en ese panel le pones el texto que quieras, estas generando una notificación propia pero sin el problema del Activity_Resume que te genera la notificacion

Tambien, aunque supongo que lo sabes, puedes lanzar la notificación al formulario (activity) donde estes, si solo empleas dos formularios lo puedes hacer con el IsPaused(NombreDelAcitivy) , si son mas de uno con una variable global activandola cuando entras . No si si sabes que tambien como parámetro del
SetInfo2 donde le pasas el activity, si le pasas un null no entrará en ningun activity, podrias emplear este sistema y el panel de aviso para dar la notificación, y cuando te den el aceptar en ese panel quitar la notificación con el cancel(n)

Saludos
 

Seneca

Active Member
Licensed User
Hola.

He repasado varias veces lo que me comentas @bgsoft y, si no te he entendido mal, lo que me indicas es que en el momento de recibir la notificación se lanza un panel (sobre la actividad que esté en pantalla) mostrando el mensaje. Si es así, no corresponde con lo que busco. Lo que deseo hacer es que al recibir el mensaje se muestre un icono en la barra superior y que sea el usuario el que decida en qué momento mostrar el mensaje push, pulsando en ese icono. Al pulsar el icono mostraría el mensaje en un Msgbox (me es igual con un panel), pero, y esto es lo complicado, deseo que la actividad de fondo permanezca invariable.

Adjunto un vídeo de ejemplo. Se puede ver que si estoy en la Actividad1 o Actividad2, al pulsar el icono de notificación primeramente me muestra la actividad Main. Lo que busco es que si estamos en cualquiera de estas dos, se me muestre el mensaje (cuando el usuario pulsa el icono de notificación) pero sin que la app vaya a Main.

He probado apuntando el Setinfo2 en vez de a Main a una actividad transparente que me muestre el mensaje, pero el efecto es igual.

Quizás sea yo el que no ha entendido lo que me indicas @bgsoft. Aunque he visto el efecto que estoy buscando en una app que uso en mi móvil, quizás no sea posible hacerlo en B4A.

Respecto al hilo que me muestras @dar2o3 lo conocía (creo que me leído el 95% de los hilos relativos a FCM) pero tampoco consigo cuadrarlo con lo que busco.

Adjunto el proyecto de ejemplo que he usado. Como base he cogido el ejemplo XerpChat del compañero @dar2o3

Saludos.
 

Attachments

  • ejemplo FCM.zip
    18 KB · Views: 264
  • video_ejemplo_FCM.zip
    300.9 KB · Views: 271

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Seneca:

he estado viendo tu ejemplo, yo te decia que crearas un activity exclusivo solo para recibir la notificación, y cuando aceptes el msgbox lo finalizas.

Si eso dices que no te vale, pues creas una variable global que cuando entres en un activity (1 o 2) la actives, entonces al principio del resume del main, cuando te llegue la notificacion dependiendo de en que activiy estuvieras haces el salto a el, antes cancelas la notificacion y despues de la llamada al acivity haces un return para que salga del resume y no te entre lo que tengas, con esta opcion creo que ni verias el main, yo lo probé tanto lo de arriba como esto y funciona, el problema que lo probé en un S8 que va como un tiro y quizas por eso no lo veo.

Saludos
 

Seneca

Active Member
Licensed User
Hola.

No he conseguido captar del todo lo que me explicas en el segundo párrafo, @bgsoft. Pero sí me has dado la pista de la solución a lo que andaba buscando. Por recordar comento que lo que ando buscando es que al recibir un mensaje desde Firebase Notifications, se muestre un icono avisando de ello en la barra superior. Cuando el usuario decida ver el mensaje pincha ese icono y, sin que se produzca un cambio de Actividad, se muestre el mensaje en lo que vendría a ser una ventana emergente (puede ser un Msgbox o un panel.)

Como el Setinfo2 (o Setinfo) obliga a apuntar a una determinada actividad (que puede ser Main o cualquier otra) visualmente se produce un cambio de actividad en pantalla desde la que estábamos a esta que se ha apuntado en el Setinfo. Lo que me he percatado, a raíz del anterior mensaje de @bgsoft, es que si nada más entrar en esta actividad se sale de ella, volvemos al Resume de la actividad en la que estábamos en el momento de pulsar sobre el icono de notificación de la barra superior, sin que visualmente se perciba un cambio de actividad.

Una vez así, desde el Resume ya puede mostrar el contenido del mensaje. He optado por hacerlo cargando un Layout donde se mostraría dicho mensaje. Como este procedimiento de mostrar el mensaje (desde el Resume de la actividad en la que estaba cuando se pulsa el icono de notificación) tendría que implementarlo en varias actividades, he intentando usar una clase de manera que no he de duplicar código. La entrada a la clase me funciona perfectamente, pero ahora me he encontrado un nuevo problema a la hora de quitar de pantalla el mensaje mostrado y salir de la clase. Como este problema es totalmente distinto al tema de este hilo haré la consulta en uno nuevo.

Como indicaba, he recurrido a una clase para evitar tener que duplicar código, aunque la programación de esta clase tiene fallos que aún no he conseguido resolver.

Adjunto el proyecto B4A, así el B4J que estoy usando para enviar los mensajes. Al B4A habría que añadirle el archivo google-services.json y al B4J la Key correspondiente.

Gracias @bgsoft por mostrarme el camino para encontrar lo que buscaba.

Saludos.


B4X:
'**** MAIN ****

Sub Process_Globals
    Dim muestra_notificacion As Boolean  
    Dim strTitulo As String
    Dim strMensaje As String
End Sub

Sub Globals
    Private Button1 As Button
    Private Button2 As Button
End Sub
      
Sub Activity_Create(FirstTime As Boolean)
  
    'Para que funcione se ha de añadir a la carpeta del proyecto el archivo "google-services.json" generado por la consola firebase y comentar esta línea
  
    Activity.LoadLayout("Mensajero")
    If FirstTime=True Then
        'Llamamos a la función suscribetopics del módulo de servicio firebasemessaging para asegurarnos de que estamos suscritos al teme seleccionado en este caso el topic se llama "general"
        CallSubDelayed(FirebaseMessaging, "SubscribeToTopics")
    End If
End Sub


Sub Activity_Resume
    'Compruebo si se ha de mostrar el mensaje
    If muestra_notificacion Then
        'Muestro el mensaje usando una clase, aunque al salir de la misma me presenta un error pendiente de resolver
        Dim notificacion As muestra_mensaje
        notificacion.Initialize("")
        notificacion.muestra ()
        'Desactivo la "variable bandera" para mostrar el mensaje
        muestra_notificacion = False
    End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub Button1_Click
    StartActivity(actividad1)
End Sub

Sub Button2_Click
    StartActivity(actividad2)
End Sub


B4X:
'**** actividad1 ****

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("actividad_1")
End Sub

Sub Activity_Resume
    'Compruebo si se ha de mostrar el mensaje
    If Main.muestra_notificacion Then
        'Muestro el mensaje usando una clase, aunque al salir de la misma me presenta un error pendiente de resolver
        Dim notificacion As muestra_mensaje
        notificacion.Initialize("")
        notificacion.muestra ()
        'Desactivo la "variable bandera" para mostrar el mensaje
        Main.muestra_notificacion = False
    End If
End Sub


B4X:
'**** activa_mensaje ****

Sub Activity_Create(FirstTime As Boolean)
End Sub

Sub Activity_Resume
    'Aquí llego desde el n.SetInfo.
    'Con la siguiente variable globar activo para que se me muestre el mensaje
    'Y luego salgo rápidamente regresando a la actividad desde la que que se pulsó el icono de notificación del mensaje
    'sin que visualmente se note este cambio de actividades
    Main.muestra_notificacion = True
    Activity.Finish
End Sub


B4X:
'**** CLASE muestra_mensaje ****

Sub Class_Globals
    'Dimensiono una actividad
    Dim actividad As Activity
    Dim lblMensaje As Label
    Dim lblTitulo As Label
    Dim btnCerrar As Button
    Dim panel1 As Panel
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize (nada As String)'actActividad As Activity)
End Sub

Sub muestra ()
    'Cargo el Layout que me muestra en el mensaje dentro de la actividad dimensionada más arriba
    actividad.LoadLayout("notificacion")
    'Relleno el campo Titulo y Mensaje dentro del Layout
    lblTitulo.Text = Main.strTitulo
    lblMensaje.Text = Main.strMensaje
End Sub

Sub btnCerrar_click
'    panel1.RemoveView
    'Al pulsar el botón intento finalizar la actividad creada, pero me salta un error
    actividad.Finish   'Salta error al intentar cerrar
End Sub
 

Attachments

  • FCMPush actualizado - sin clave.zip
    3 KB · Views: 246
  • ejemplo FCM 2.zip
    19.2 KB · Views: 245
Last edited:

Seneca

Active Member
Licensed User
Hola.

Una vez me han ayudado a resolver el funcionamiento de la clase en este hilo, actualizo el código que ya funciona correctamente al completo. Ahora ya puedo abrir la notificación recibida con Firebase Notifications, mostrándose esta en ventana emergente cuando se pulsa el icono de dicha notificación.

Saludos.

B4X:
' **** MAIN ****

Sub Process_Globals
    Dim muestra_notificacion As Boolean
    Dim strTitulo As String
    Dim strMensaje As String
End Sub

Sub Globals
    Private Button1 As Button
    Private Button2 As Button
End Sub
     
Sub Activity_Create(FirstTime As Boolean)
 
    Para que funcione se ha de añadir a la carpeta del proyecto el archivo "google-services.json" generado por la consola firebase y comentar esta línea
 
    Activity.LoadLayout("Mensajero")
    If FirstTime=True Then
        'Llamamos a la función suscribetopics del módulo de servicio firebasemessaging para asegurarnos de que estamos suscritos al teme seleccionado en este caso el topic se llama "general"
         CallSubDelayed(FirebaseMessaging, "SubscribeToTopics")
    End If
End Sub


Sub Activity_Resume
    'Compruebo si se ha de mostrar el mensaje
    If muestra_notificacion Then
        'Muestro el mensaje usando una clase
        Dim notificacion As muestra_mensaje
        notificacion.Initialize(Activity)
    End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub Button1_Click
    StartActivity(actividad1)
End Sub

Sub Button2_Click
    StartActivity(actividad2)

B4X:
'**** actividad1 ****

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("actividad_1")
End Sub

Sub Activity_Resume
    'Compruebo si se ha de mostrar el mensaje
    If Main.muestra_notificacion Then
        'Muestro el mensaje usando una clase
        Dim notificacion As muestra_mensaje
        notificacion.Initialize(Activity)
        'Desactivo la "variable bandera" para mostrar el mensaje
        Main.muestra_notificacion = False
    End If
End Sub

B4X:
'**** activa_mensaje ****

Sub Activity_Resume
    'Aquí llego desde el n.SetInfo.
    'Con la siguiente variable global activo para que se me muestre el mensaje
    'Y luego salgo rápidamente regresando a la actividad desde la que que se pulsó el icono de notificación del mensaje
    'sin que visualmente se note este cambio de actividades
    Main.muestra_notificacion = True
    Activity.Finish
End Sub

B4X:
'**** CLASE muestra_mensaje ****

Sub Class_Globals
    'Dimensiono una actividad
    Dim actividad As Activity
    Dim lblMensaje As Label
    Dim lblTitulo As Label
    Dim btnCerrar As Button
    Dim pnl As Panel
    Dim pnlBase As Panel
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize (parent As Object)
    'Desactivo la "variable bandera" para mostrar el mensaje
    muestra_notificacion = False

    pnl.Initialize("")
    pnlBase.Initialize("pnlBase")
 
    actividad = parent
    actividad.AddView(pnlBase,0,0,100%x,100%y)
    pnlBase.AddView(pnl,4%x,20%y,92%x,76%y)
 
    'Cargo el Layout dentro del Panel
    pnl.LoadLayout("notificacion")
    lblTitulo.Text = Main.strTitulo
    lblMensaje.Text = Main.strMensaje
End Sub

Sub btnCerrar_click
    pnlBase.RemoveView
    Return
End Sub

Sub pnlBase_Click
End Sub
 

Attachments

  • ejemplo FCM 3.zip
    19.1 KB · Views: 244
Last edited:
Top