Lessons learnt: In Firebase Spark plan, simultaneous connections limit is 100!

Lessons learnt: In Firebase Spark plan, simultaneous connections limit is 100!

My latest Android app with Kotlin, Owly, displays one fact a day on your screen. Simple. The way I designed it is, a job is scheduled to work at 13:00 local time every day and when the job is triggered, it’s making a call to Firebase database to retrieve a Fact object to the device.

It all worked very well in the first week. Zero crash rate. Zero complaints. In the second week, I started getting emails saying that

App doesn’t show a new fact. All I see is the old ones!

I’m using Crashlytics for automatic bug reporting but wasn’t getting any reports. Then I checked logs and realized despite of making the call to Firebase database, application was not receiving any data!

After narrowing the issue down that much, I finally figured out what was wrong: I had 700+ active users and they were all trying to get the data from server at the same time (13:00)! When I was scheduling the job, I just didn’t think about the simultaneous connection limit of Firebase – which was only 100 in the Spark(free) plan. Therefore all connection requests after the 100th one was being refused.

Solution

Well the easiest solution could be upgrading to Blaze plan which was allowing 100.000 concurrent connections (when you pay $25 per month). What I did though was to change the fact retrieving time for users, setting a random time between 11am and 3pm:

That worked pretty well and we don’t have any issues at the moment. As expected, database connection went back to the desired levels, around 20 at a time:

Hope you remember to check your backend limits when you’re up to something. Price you pay for not doing so maybe a lot more than couple of uninstalls I had!

Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
Owly – A pet project in Kotlin (Part I)

Owly – A pet project in Kotlin (Part I)

What is it and Why?

Owly is a small Android application I developed in Kotlin, as a pet project. On a lazy Sunday afternoon my brother came up with the idea of an app that delivers a fact as a notification every day. OK, maybe not the most interesting or challenging idea out there but still a good start to actually do something with a brother.

Me & my brother: Who is the developer (guess who)?

He took the role of Product Owner (also responsible with marketing  & distribution) and I became the Kotlin developer (surprise surprise). My motivation behind it was obviously to learn Kotlin! I’ve been reading and reading about it for quite some time and was very interested & excited, just didn’t have any chance at work to try. Owly seemed like a good chance to get my hands dirty.

We started toying with the idea and drawing screens on papers. Even after all these years in professional app development, I’m still amazed with the fact that there are A LOT to discuss and decide even for such a (relatively) small app.

   

A fact delivered. Users can swipe left to see the images of the fact or scroll up and down to access the previously delivered facts. To vote a fact, users have like and dislike buttons (red and green smileys at the bottom).

5 Weeks of development: Evenings & some of the weekends only

Anyway we agreed on basics and I started my first Kotlin project. Within first week, we had a working concept that delivers the facts. The remaining 4 weeks were all about adding all that nice to haves, improvements (so to speak), a lot of “shall we use a lighter red colour here” s – well you probably know how it is. I’m a little bit crushed with the excitement and amateur soul of my brother – who is a physiologist by profession by the way (he runs a care home during the day).

After like 5 weeks, we were ready to publish the app. We published for Turkey only (where my brother resides) and started working on marketing right after. These days he’s quite busy with that but marketing is probably a topic for another post.

Well from my view of point project was very succesfull:

  • 87% of the code is in Kotlin which means I succeeded at what I aimed – learning Kotlin
  • Idea to market only in 5 weeks, working in the evenings and at some weekends only
  • Used tones of new stuff and improved my existing skills during the development
  • Maybe the most important part – I enjoyed working on it A LOT! So much fun

Technologies used

  • Developed with Kotlin (around 87% of the code)

  • Firebase as the backend: We used Realtime NoSQL database, Firebase authentication, Crashlytics and Firebase Analytics. Awesome stuff, very happy with it.
  • Async programming with Firebase API: Nice and smooth user experience through the application.
  • WorkManager, OneTimeWorkRequest and PeriodicWorkRequest to schedule the fact delivery in the most optimal way (awesome stuff, seriously!). No load on device processor.
  • Recyclerview and CardView for the facts. High performance scrolling, swiping fact cards to vote and remove from the deck.
  • Constraint layout for UI
  • User preferences: PreferenceFragment loading preferences xml from resources – nice, clean and ‘familiar’ preferences screen.
  • Multiple language support

Design patterns

Used MVVM, Observer Design Pattern, Singleton, Async development, Adapter pattern with the app.

Some screenshots

 

Part 2

In part 2, I’ll talk more about how Owly works, from a technical view of point.

 

Get it on Google Play

Fading overlay when swiping a RecyclerView item

Fading overlay when swiping a RecyclerView item

If you don’t know already, RecyclerView is a state-of-art library in Android SDK. You can do pretty much everything with RecyclerView.

In this article I’ll quickly show you how to overlay a fading View on top of a RecyclerView item, as seen below:

ItemTouchHelper.Callback

ItemTouchHelper is a useful callback that we attach to RecyclerView to learn about the item’s (row’s) movement. First thing we need to do is to create a callback variable:

private val itemTouchCallback = object : ItemTouchHelper.Callback() {
   // override the methods
}

This callback has the methods that I haven’t put here but below we’ll be implementing one of them. Now we need to attach our recycler view to an ItemTouchHelper that takes our itemTouchCallback as its callback:

val itemTouchHelper = ItemTouchHelper(simpleItemTouchCallback) 
itemTouchHelper.attachToRecyclerView(recyclerView)

Now our callback will notify us about any movements of the recyclerView items, including swiping right and left. Now let’s see the implementation of the callback:

private val itemTouchCallback = object : ItemTouchHelper.Callback() {
    override fun getMovementFlags(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int {
        return makeMovementFlags(0, ItemTouchHelper.START or ItemTouchHelper.END)
    }

    override fun onMove(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?, target: RecyclerView.ViewHolder?): Boolean {
        return false
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder?, direction: Int) {

        if (direction == ItemTouchHelper.START)
            doSomething()
        else if (direction == ItemTouchHelper.END)
            doAnotherThing()
    }

    override fun onChildDraw(c: Canvas?, recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
        val holder: FactViewHolder = viewHolder as FactViewHolder
        holder.likeImage.alpha = Math.max(if (dX > 0) dX / OPACITY_COEFFICIENT else OPACITY_MIN, OPACITY_MIN)
        holder.dislikeImage.alpha = Math.max(if (dX < 0) Math.abs(dX) / OPACITY_COEFFICIENT else OPACITY_MIN, OPACITY_MIN)
        holder.likeImage.invalidate()
        holder.dislikeImage.invalidate()

        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
    }
}

getMovementFlags

Override this method just to indicate what moves we’re interested in. In the code above we are returning START and END flags meaning we’re interested in user moving the items left and right.

onSwiped

Here do whatever you need to do depending on the swipe direction.

onChildDraw

Now this is the method we need! It’s fired each time children of the item are drawn. Here depending on the change in x direction (dX), we’re setting the alpha value of the like / dislike images. Then we invalidate them (not sure we need that invalidation, I’ll re-check!)

And the result is as seen in the image above. Pretty easy isn’t it?

Sound issue with NotificationChannel

Sound issue with NotificationChannel

As you may already know, you need to create a Notification channel with NotificationChannel when targeting devices with Android O (API 26+) and above (ie. Android Pie, API 28!)

The little problem about the notification channel is that once it’s created, you cannot change some of the properties, like sound. That means at the time of first run, the ringtone you used, say, will stay even if you change it afterwards (ie. from your app’s settings)

notificationChannel.setSound(notificationSoundUri)

So once this line is executed, the same sound will play even if you change the URI of the ringtone later. That was one of the problems I had on a project I was working on. In that project users were allowed to change the notification ring from Settings (because hey why not?) and although they change and set a new ringtone, they were still hearing the old, classic, default device ringtone.

However, the mystery is solved as mentioned above.

Solution

Well, the solution is actually not to use setSound method! Instead, we need to set notification importance level to IMPORTANCE_LOW and play the ringtone ourselves when the notification is about to be displayed:

val notificationChannel = NotificationChannel("channel_id_here", "channel_name_here", NotificationManager.IMPORTANCE_LOW)

Setting importance low will ensure that device will not play the notification. Then we can play the ringtone ourselves:

private fun playSound(soundUri: Uri) {
    try {
        if (soundUri.toString() == "") return

        val ringtone = RingtoneManager.getRingtone(applicationContext, soundUri)
        ringtone.play()
    } catch (e: Exception) {
        // log that
    }
}

Not that bad eh? Let me know below what you think!

Firebase anonymous authentication with Kotlin

Firebase anonymous authentication with Kotlin

Sometimes all you need is to authenticate your users in the quietly in background. No emails, no passwords or social media accounts. For Owly, my latest pet project, that was exactly what I needed.

  • Go to Firebase console > Your project > Database > Rules

Set read / write permissions as below:

{
"rules": {
".read": "auth != null",
".write":"auth != null"
}
}

That simply means to read and write users should be authenticated in one of the allowed ways.

  • Now in your code, simply call Firebase instance authenticate method and listen for the result:

FirebaseAuth.getInstance().signInAnonymously().addOnCompleteListener {
   Logger(this).log(
      if (it.isSuccessful) "sign-in successful" else "sign-in failed"
      , LogEvent.OTHER
   )
}

Well believe or not, that does the job. Happy coding.