elegantmonkeys / monaka

An Akka based FCM server based on XMPP protocol

GitHub

Monaka

Codefresh build status

A Scala library based on Akka for writing FCM (Firebase Cloud Messaging) application server side using XMPP protocol. The XMPP API provides a much richer functionality compared to the HTTP API.

For more information about the name.

Installation

Add the following to your build.sbt

libraryDependencies += "com.elegantmonkeys" %% "monaka" % "1.0.0-RC1"

Getting Started

  • You must create a Firebase project and to receive sender id and server key.
  • Override fcm.user and fcm.key in application.conf as follows:
fcm {
  user = "<sender id>"
  key = "<server key>"
}
  • For more configurations refer to the reference.conf (e.g. setting the fcm server to pre-prod environment)
  • Create a FcmXmppServer actor using FcmXmppServer.apply
private final val config = ConfigFactory.load

val system: ActorSystem = ActorSystem("FcmAppServer")

val fcmXmppServer = FcmXmppServer(FcmConfig(config)) { props =>
  system.actorOf(props, name = "fcmXmppServer")
}
  • Send a Connect message to connect to FCM server fcmXmppServer ! Connect
  • Send a downstream message to your client
val id = "m-" + UUID.randomUUID().toString
val message = DownstreamMessage("<registration token>", id, Map("myfield" -> "myvalue"))
fcmXmppServer ! SendDownstreamMessage(message)
  • The actor will respond with DownstreamMessageSent when an ack is received from FCM server and if receipt is to true only when a delivery receipt is received.
  • If the operation failed the actor will respond with DownstreamMessageFailed

Example

object FcmApp extends App {
  private final val log: Logger = LoggerFactory.getLogger(FcmApp.getClass)
  private final val config = ConfigFactory.load

  val token = config.getString("token")
  val system: ActorSystem = ActorSystem("FcmAppServer")

  log.info("Hello FCM Akka Server")

  val fcmXmppServer = FcmXmppServer(FcmConfig(config)) { props =>
    val supervisor = BackoffSupervisor.props(
      Backoff.onFailure(props, childName = "fcmXmppServer", minBackoff = 1.seconds, maxBackoff = 10.seconds, 0.2)
        .withAutoReset(10.seconds)
        .withSupervisorStrategy(OneForOneStrategy() {
          case _ => SupervisorStrategy.Restart
        })
    )

    system.actorOf(supervisor, name = "fcmXmppServerSupervisor")
  }

  fcmXmppServer ! Connect

  0.to(5).foreach { index =>
    Thread.sleep(5000)

    val id = "m-" + UUID.randomUUID().toString
    val message = DownstreamMessage(token, id, Map("myfield" -> index.toString), receipt = true)
    fcmXmppServer ! SendDownstreamMessage(message)
  }
}

Credits

Thanks to fcmxmppserverv2 for the amazing reference!

Monaka