An internal Google survey conducted last year found that more than 40% of the one-star apps in the Play Store had stability issues. On the other hand, people tend to rate and review high-performing apps better and better, leading to higher rankings on Google Play and more downloads. Not only that, users are more engaged and willing to spend more time and money on these apps.
Therefore, solving the problem of application stability can significantly affect the success of the application.
By objectively measuring app quality, developers can easily identify stability issues that need to be addressed, which is why we’ve added a new section on the Google Play Console called Android Vitals. With Android Vitals, developers can learn about performance and stability issues without having to add additional tool code or libraries. Android Vitals collects anonymous data related to application performance when an app is running on a large number of devices. The amount of information gained in this way is unmatched in any other way, even by hardware lab tests.
Android Vitals can send developers three alerts: crashes, unresponsive applications, and times of rendering. All three have a direct impact on the user experience and how they evaluate the app. In addition, users may not directly associate bad behavior like “abnormal power consumption events” with your application.
This article will explore two of these issues:
1. Over-arousal: Over-arousal can affect battery life and may prevent the user from continuing to use the device without timely charging. This behavior can cause users to uninstall your application quickly;
2. Application unresponsive (ANR) events: This event is triggered when the application’s user interface is stuck. When the interface freezes, if your application is running in the foreground, a dialog box will appear to remind the user to “close the application” or “wait for a response”. This kind of behavior is just as bad for users as an app crash. They may not uninstall your application right away, but if the ANR issue is not resolved, there is a good chance they will look for an alternative application.
Excessive awaken
To extend battery life, when the screen is off, the Android device disables the main CPU core and goes into deep sleep mode. Unless the user wakes up the device, it is best to leave it in this state for as long as possible. However, it is still necessary to wake up the CPU and warn the user in the event of some event — for example, an alarm is triggered or a new message is received. Wakeup alarm can be used to handle such warnings, though it doesn’t have to be, as explained below. So far, waking up seems like a great way to get important things to the user’s attention, but waking up too many times can backfire and damage battery life.
How does Android Vitals show excessive arousal
Android Vitals can help developers know if their apps have too many wakeups. By collecting anonymous data about app behavior, Android Vitals can show what percentage of users experience more than 10 device awakenings per hour after their device is fully charged. The key is to look for a red icon, which means your app has crossed the bad behavior threshold and is one of the worst performing apps on Google Play, and you need to improve your app’s behavior.
Is there any other way to wake up the alarm?
The RTC_WAKEUP or ELAPSED_REALTIME_WAKEUP flags are set primarily through the AlarmManager API to wake up the device at a specific time or after a certain interval. This feature should be used with caution and only in the absence of other superior task scheduling and notification mechanisms. When using a wake up alarm, you need to consider the following:
- If you need to display information in response to data coming from the network, consider using tools such as Firebase Cloud Messaging to implement message push. By using this mechanism, rather than polling regularly for new data, your application will wake up only when it needs to.
- If you can’t use message push and rely on regular polling, consider using JobScheduler or Firebase JobDispatcher (or SyncManager for account data). They have a higher API level than AlarmManager and have the following advantages for intelligent task scheduling:
Batch operation: Batch operation of tasks rather than multiple awakenings of the system for operation, which enables the device to stay asleep for longer periods of time.
Criteria: You can specify specific criteria that a task must meet, such as network availability or battery charging status. Setting standards can avoid waking up devices and running unnecessary applications.
Persistence and automatic retreat continue to execute tasks (even after restart) and automatically retry in case of failure.
— Low Power Mode (DOZE) compatibility — Tasks can only run in low power mode or when no limits are set for applying standby mode.
You can use AlarmManager to set the alarm to wake up if and only if the notification push and task scheduling are not applicable to your task. To put it another way, waking the alarm is necessary only if you want to trigger it at a certain time, regardless of network and other circumstances.
What should you do when Android Vitals displays excessive arousal?
To solve the problem of over-arousal, you need to identify where your application sets wake-up alarms and then reduce the frequency at which those alarms are triggered.
So how do you see where your app is setting the wake-up alarm? You can open the AlarmManager class in Android Studio, right click on the RTC_WAKEUP or ELAPSED_REALTIME_WAKEUP field, select “Find Lead “, You can then see all the events in your project that use such flags. Take a close look at each type of event, and then consider whether you can switch to a more intelligent task scheduling mechanism.
If you think using a wake up alarm is unavoidable, Play Console can provide better analysis data if your alarm label meets the following requirements:
- Include the package, class, or method name in the alarm tag. This also helps you easily determine where the alarm is set in the source;
- Do not name the alarm using Class#getName(), as Proguard will confuse this. Use hard-coded strings;
- Do not add counters or other unique identifiers to alarm tags, because the system may be too difficult to remove such tags and cannot count them in valid data.
The application cannot respond
For users, ANR is the event when they try to interact with the application, but the interface gets stuck. After a few seconds, a dialog box will appear giving the user the option to continue to wait or forcibly stop the application.
From a developer’s perspective, ANR is when an application runs an operation that takes too long, such as disk or network I/O, causing the main thread to block. The main thread (sometimes referred to as the UI thread) is responsible for responding to user events and refreshing the screen 60 times per second. It is therefore critical to transfer any operations that might delay the main thread to the background thread.
How does Android Vitals display unresponsive applications?
Android Vitals collects and leverages anonymous data on application ANR events to provide multiple levels of ANR specific reporting. The main screen provides an overview of ARN activity in your application, shows the percentage of daily conversations that users have experienced at least one ANR event, and provides separate reports for the previous day and the first 30 days. It also provides a threshold for bad behavior.
The application cannot respond to common causes
As mentioned above, ANR events are triggered when an application process affects the main thread. The reasons for this blocking are different, but the most common ones are:
- Perform disk or network I/O on the main thread. This is by far the most common cause of ANR. While most developers agree that you shouldn’t read or write to disk or network on the main thread, sometimes we just can’t help it. Ideally, reading a few bytes of data from disk would not trigger an ANR, but it’s never a good idea. If your user’s device has a slow flash memory and your application is queuing up to run “fast” reads while other applications are already stressing the device, it’s really not wise to run I/O on the main thread.
- Run a long calculation on the main thread. What about in-memory calculations? Long access times should not affect memory, and smaller operations should be fine. But if you start looping through complex calculations and processing large data sets, the main thread can easily block. You can consider resizing large megapixel images, or displaying the text into a TextView after parsing large chunks of HTML text. In general, it is better to let the application run this operation in the background;
- Synchronous calls to another process on the main thread binder: Similar to disk or network operations, program execution is shifted to places beyond your control when blocking calls are made between threads. What if other processes are busy? What if you need to access your disk or network in response to your request? In addition, data has to go through parcel and unparcel before it can be transferred to another process, which can take a lot of time. Therefore, interprocess calls from background threads are still recommended;
- Use synchronization: Even if you move complex operations to background threads, you still need to communicate with the main thread to display the results. Multithreaded programming is not easy, and it is difficult to ensure that execution does not block when using synchronous locks. In the worst case, you can have a deadlock problem, where different threads get stuck. It is better not to design synchronization yourself, but rather to use a specialized solution, such as a Handler, to pass immutable data from the background thread back to the main thread.
How do I detect why an application is not responding
Finding what triggers ANR is not easy. Let’s take the URL class as an example:
- Do you want to see URL#equals (the method to determine whether two urls are the same) block the thread? What about SharedPreferences?
- If you are reading values in the background, can you call getSharedPreferences in the foreground?
Both cases are likely to result in long blocking operations. Luckily we have StrictMode so we don’t have to guess what causes ARN. When debugging builds, you can use this tool to catch unexpected disk or network access on the main thread.
You can use StrictMode#setThreadPolicy in your application to customize the check items, including disk and network I/O and the slow calls that you trigger through StrictMode#noteSlowCall in your application. You can also choose how StrictMode tells you that a blocking call has been detected: an application crash, logging, or a dialog box? See the ThreadPolicy.Builder class for further information.
Once you’ve eliminated blocking calls on the main thread, remember to turn StrictMode off before uploading your app to the Play Store again.
Solving the problem of over-arousal and ANR can improve the quality and stability of your app, improve your app’s ratings, generate more positive reviews, and ultimately increase downloads. Using Android Vitals allows you to quickly and easily understand the problems that need to be solved in your application. Finding and solving these problems in your code may not be easy, but you can use tools and techniques to do your job effectively.
Check out Android and Google Play content here