Love is Everything

From the moment babies open their blurry eyes, all they seek is love Food, water, shelter — they can allow a person to survive But to live, to flourish Our soil must be watered with love To grow, to…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




ANRs and the challenge to show ads

It was a year ago when I first heard about ANRs. It was after my team in Wildlife Studios introduced a new way to display ads in our games.

ANR stands for Application Not Responding, and it happens when the UI thread of any Android application is blocked for too long (~5 or more seconds for being counted by Google). You probably experienced at least one of them in your favorite application. It looks like this:

Figure 1. Example on how a Android shows an ANR

The dialog gives the user the option to force quit the app. It’s a really bad user experience :(

An ANR will be triggered for your app when one of the following conditions occur:

When your app exhibits a rate of occurrence equal to or higher than 0.47% (the famous Google threshold, meaning percentage of affected sessions w/ANRs), it’s in the bottom 25% of the top 1,000 apps on Google Play (by the number of installs). Your application will be more difficult to be found in organic search results.

When your application is suitable for monetizing by showing ads, I have to be honest, it’s something you can do super quick. You will likely have your first ad displayed to a user in less than a week.

The challenge behind this is to keep your application healthy in terms of ANRs (and crashes). During 2021 in Wildlife we tested multiple solutions, from our own to the industry top mediations, and they all faced the same issues.

There are multiple reasons why showing ads is challenging, I will describe the most important for me, and it’s likely I still do not know all of them:

When comes to show ads, there comes the ads networks. They are the source of the ads, and you need more than one to increase the possibility of fulfilling an ad opportunity: Admob, Facebook, Applovin, ironSource, UnityAds, Vungle, TikTok, etc, etc. There are a lot and most of them come with a pretty SDK. They are like the air, you need them.

Just to give an example: Facebook can be very effective for 40–50-year-old people but have less efficiency for a teenager, whereas TikTok could responde better for youth.

This is why people use a mediation SDK to handle multiple networks under a single API.

Each library you include, it’s a box of surprises in terms of functionality and performance. System calls, HTTP requests, parsing JSON, storing information in the Shared Preferences, writing into a database, pieces of code you do not control and you do not know are happening while you are running your application.

The more you add, the more resources your application will consume. Keep the number low enough as much as the business lets you.

Long short story, every time you show an interstitial or rewarded video ad, behind the scenes an Activity is created. When the ad is closed, there are two events triggered, onPause & onStop. Most of the libraries do stuff when an activity is paused or stopped: logging, checking the battery status, connection, etc.
When you add a mediation to your application to monetize, you are adding more folks to the party. Each of them wants to do their stuff during the activity lifecycle. The more libraries, the more time your application will stay processing after an activity is manipulated.

Figure 2. Flamegraph showing multiple networks running their code in the main thread after an Activity has paused.

You have a way to lower the impact of adding a mediation to your application and is by having only those ad networks that make money and leave out of the table those that doesn’t worth it. Keep in mind that only by having the library included, the SDK will automatically hook (even without calling the lib initialization!) to the lifecycle events and do their duty.

The rendering of a WebView is quite slow. The resource download and the rendering are in the UI thread. Now you know that everything that happens in that thread can lead to ANRs.

Trying to find the root cause of an ANR is quite an experience, so you want to try to keep them away from your life as much as possible. Here are some tips you can follow to keep your application responsive for the user:

I will list this as the first one because every Android application has access to the Android Vitals section in GPC.
Google Play Console presents a list of ANRs with the number of occurrences and impacted users. When you go into detail for one of the ANRs, you can or not have a thread dump attached to the offender. So, in case you do not have the thread dump, you are blind. The root cause of that ANR is unknown and you also do not know if it’s only one or multiple causes.

If you are lucky enough, you will have a thread dump waiting for you. Most of the time the snapshot taken by Google is not enough to find out the root cause of an ANR. ANRs appear when your application is unresponsive for more than 5 seconds, so it’s hard to find out the cause by just looking at only one snapshot of the ANR timeline.

Okay, so having just a thread dump it’s not enough to diagnose ANRs. Which tool do I know that lets me find out what is happening in my application through time? There is when it comes to the flame graphs.

A flame graph is a way of visualizing your application call stack. Along the x-axis are groupings of functions across the sampling period. The wider the bar on the x-axis, the longer the frame has spent on the CPU. The y-axis shows the depth of our call stack, having a clear path to the root of each function call.

Figure 4. Flamegraph showing multiple pieces of code running when a message is handled

When talking about ANRs, this tool puts more clarity on which are the most common code paths consuming CPU time in the main thread, therefore which pieces of code we need to improve to provide the largest gains. The code to be fixed could be yours, from another team, or even from a third-party lib. The main gain about using a flame graph is reducing considerably the engineering time to spot action points to then measure the impact in terms of ANRs.

The art of profiling an application applies not only to mobile but to software in general. The idea is to collect information about the resources used by our application, like CPU, memory, disk, etc. In the case of Android, you can profile your app using Android Studio by building it or using a debug APK. You should focus on the calls executed in the main thread.

To start debugging an APK, click Profile or debug APK from the Android Studio Welcome screen. Or, if you already have a project open, click File > Profile or Debug APK from the menu bar. In the next dialog window, select the APK you want to import into Android Studio and click OK.

I quickly covered months of experience leading the efforts of lowering ANRs for multiple live games. Here are the principal keynotes:

Good luck!

Add a comment

Related posts:

How to Rotate a Video by a Few Degrees

When you record a video on your mobile phone and then transfer it to a computer or TV for viewing, you often see the video rotated 90 degrees or even flipped 180 degrees. However, there are also…