Debug ANRs

Solving ANRs in your Unity game is a systematic process:

Figure 1. Steps to solve ANRs in Unity games.

Integrate reporting services

Reporting services such as Android vitals, Firebase Crashlytics, and Backtrace (a certified Unity partner) provide error logging and analysis for your game at scale. Integrate reporting services SDKs into your game early in the development cycle. Analyze which reporting service best fits your game needs and budget.

Different reporting services have different ways of capturing ANRs. Include a second reporting service to increase the chance of obtaining valid data to support your decision in fixing ANRs.

Integrating reporting SDKs doesn't impact game performance or APK size.

Analyze symbols

Analyze the reports from your reporting service and check whether the stack traces are in human-readable format. See Symbolicate Android crashes and ANR for Unity games for more information.

Figure 2. Crashlytics showing build ID and missing libil2cpp.so symbols.

How to check symbol build ID

If the reporting system shows the missing build ID but the build symbols still exist in the build machine storage, it's possible to check the build ID of the symbols and then upload them to the reporting service. Otherwise, a new build is required to upload the symbol files.

On Windows or macOS:

  1. Navigate to the symbols folder based on your scripting backend (see Resolution:)
    1. Use the following command (on Windows, use Cygwin to run the readelf utility)
    2. Grep usage is optional to filter the text output
    3. Look for Build ID
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

Inspect game code

When the stack trace shows a function in the libil2cpp.so library, the error happened in the C# code, which is converted to C++. The libil2cpp.so library has not only your game code but also plugins and packages.

The C++ filename follows the assembly name defined in the Unity project. Otherwise, the filename has the default Assembly-C# name. For example, figure 3 shows the error on file Game.cpp (highlighted in blue), which is the name defined in the Assembly Definition file. Logger is the class name (highlighted in red) in the C# script, followed by the function name (highlighted in green). Finally is the full name that the IL2CPP converter generated (highlighted in orange).

Figure 3. Test project call stack from Backtrace.

Inspect your game code by doing the following:

  • Examine the C# project for any suspicious code. Usually, C# unhandled exceptions don't cause an ANR or application crash. Even so, ensure the code runs properly in different situations. Check whether the code uses a third-party engine module, and analyze whether a recent release introduced the error. In addition, review whether you have recently updated Unity or whether the error only happens on specific devices.
  • Export the game as an Android Studio project. With complete access to your game's converted C# source code, you can find the function that's causing the ANR. The C++ code looks very different from your C# code, and the code conversion rarely has an issue. If you do find something, file a support ticket to Unity.
  • Review the game source code and ensure that any logic running in the OnApplicationFocus() and OnApplicationPause() callbacks is appropriately cleaned up.
    • The Unity engine has a timeout to pause its execution; excessive workload on these callbacks can cause an ANR.
    • Add logs or breadcrumbs to parts of the code to enhance your data analysis.
  • Use the Unity Profiler to investigate the game's performance. Profiling your app can also be a great way to help identify bottlenecks that might be causing the ANR.
  • A great way to identify long I/O operations on the main thread is to use strict mode.
  • Analyze the Android Vitals or another reporting service history and check the release versions of the game for which the error is happening the most. Review your source code in your version control history and compare code changes between releases. If you find something suspicious, experiment with each change or potential fix individually.
  • Examine the Google Play ANR reporting history for the devices and Android versions receiving the most ANRs. If the devices or versions are outdated, chances are you can safely ignore them if doing so doesn't impact the game's profitability. Study the data carefully since a particular group of users will no longer be able to play your game. For more information, see Distribution dashboard.
  • Review the game source code to ensure you are not calling any code that might cause an issue, for example, finish can be destructive if not used correctly. See the Android developer guides to learn more about Android development.
  • After reviewing the data and exporting the game build to Android Studio, you're dealing with C and C++ code, and so you can take full advantage of tools beyond Unity's standard solutions, such as Android Memory Profiler, Android CPU Profiler, and perfetto.

Unity engine code

To know if an ANR is happening on the Unity engine side of things, check for libUnity.so or libMain.so in the stack traces. If you find them, take the following steps:

  • First, search the community channels (Unity Forums, Unity Discussions, Stackoverflow).
  • If you do not find anything, file a bug to resolve the problem. Provide a symbolicated stack trace so the engine's engineers can better understand and solve the error.
  • Check whether the latest Unity LTS has made improvements related to your issues. If so, upgrade your game to use that version. (This solution may be possible only for some developers.)
  • If your code uses a custom Activity instead of the default, review the Java code to ensure the activity is not causing any issues.

Third-party SDK

  • Check that all third-party libraries are up to date and don't have reports of crashes or ANRs for the latest version of Android.
  • Go to the Unity Forums to see if any errors have already been resolved in a later version or if a workaround has been provided by Unity or a community member.
  • Review the Google Play ANR report and ensure the error has not already been identified by Google. Google is aware of some ANRs and is actively working to fix them.

System library

System libraries usually are far from the developer's control, but they don't represent a significant percentage of ANRs. Beyond contacting the library developer or adding logs to narrow down the problem, system library ANRs are difficult to resolve.

Exit reasons

ApplicationExitInfo is an Android API for understanding ANR causes. If your game is using Unity 6 or later you can call ApplicationExitInfo directly. For older Unity versions, you need to implement your own plugin to enable ApplicationExitInfo calls from Unity.

Crashlytics also uses ApplicationExitInfo; however, your own implementation gives you finer control and enables you to include more relevant information.