Embrace’s iOS and Android SDKs are now built on OpenTelemetry!

Read the release
Crash Reporting

Preventing Unity crashes in background services and background threads

Background services and background threading are a vital part of any mobile application, but they can also be a source of crashes and other issues. To ensure the smooth operation of background services and threads, monitoring and analyzing their performance using metrics is essential.

Two often overlooked factors that can contribute to mobile Unity crashes are the use of background services and background threads. They are crucial for improving game performance by moving expensive tasks off the main thread so players don’t experience sluggish performance while playing the mobile game. However, if the service metrics and threads are not properly tracked and managed, they can cause stability issues and crashes. 

In this post, we’ll cover the importance of tracking interactions with background services to resolve background threading issues causing Unity crashes on mobile. We will also share tips and best practices for optimizing your Unity games’ background services and background threads.

What is a background service?

A background service is a type of service that runs in the background of a mobile device and performs tasks without requiring user interaction. These services are essential for many apps that must perform tasks continuously or periodically.

Several different types of background services run on mobile devices. Below we will highlight the three most common services: 

OS services

The first category of background services that run on mobile are OS services, which are built into the operating system and used by various apps. For example, the Android Download Manager is an OS service that manages the download of files and media in the background. However, requesting information from an OS service on the main thread can cause ANR (Application Not Responding) or crash issues. Therefore, accessing the ADM via a background thread and transmitting that information to your app is best.

Native services

Another background service type consists of native services, such as Google Play Services. These services are provided by the device manufacturer and are used by apps to perform various tasks. For example, updating someone’s Google Play score could block the main thread, leading to performance issues.

App services 

Apps can also register their own services, such as message services, to read incoming text messages or communicate with backend databases. However, avoiding synchronous communication with these services is essential as it can cause ANRs, crashes, and other issues such as race conditions and resource contention.

How do background services impact app performance?

Background services can significantly impact mobile device performance, particularly in terms of battery life. The more background services an application uses, the more resources it will consume, which can result in a faster battery drain. This is because background services require processing power and memory to function (including a minimum amount of overhead) and can prevent the device from entering an idle state when it is not in use.

Developers should be mindful of this when designing their applications and strive to minimize the number of background services used. By reducing the number of services, developers can help optimize their applications’ performance and ensure they are not needlessly draining their users’ batteries while minimizing the required amount of cross-communication.

What is a background thread?

A background thread is a separate thread of execution that runs in the background of an application. These threads perform tasks that do not affect the user interface or block the main thread. Some common examples of background threads that run on mobile devices include:

Data synchronization

Background threads can be used to synchronize data with a server, ensuring that the user’s data is always up-to-date.

Audio playback 

Music players, video players, and other media players use background threads to play audio in the background while the user interacts with other parts of the application.

Location tracking

Applications that require location tracking, such as maps and GPS navigation apps, use background threads to continuously monitor the user’s location.

Push notifications

Background threads can be used to handle push notifications from servers, allowing the app to receive notifications even when it’s not in the foreground.

How do background threads impact app performance?

While background threads are essential for specific tasks, similarly to background services, they can impact a mobile device’s battery life and slow down the device. To mitigate these issues, developers should ensure that background threads are only used when necessary and optimized to minimize their impact on the device.

Why should Unity game developers use background services and background threads?

Background services and threads enable developers to perform critical operations in the background without disrupting the user experience. Some of the reasons why developers should use background services and optimize their background threads include the following:

Improved performance

Background services can be used to offload heavy processing tasks from the main thread, which can improve application performance and responsiveness.

Long-running operations

Background threading can improve performance for long-running operations such as downloading large files, uploading data to servers, or running complex algorithms. By offloading these tasks to a separate background thread, the application can remain responsive to user input without getting locked up or slowed down.

Processing large amounts of information

Background threads are useful for processing large amounts of information, such as complex calculations or data analysis. Doing this on the UI thread can cause the app to become unresponsive, so using background services for these tasks is crucial.

Media operations

Background threading is essential for media-related operations such as recording audio or capturing photos or videos. These tasks require continuous processing, and a background thread ensures they continue. By using a background thread for media operations, the application can also reduce the likelihood of audio or video stuttering or dropping frames.

Background updates

Background services can update data in the background, such as fetching new emails or push notifications, syncing data with a server, or downloading new content.

Overall user experience

Developers can provide a smoother and more seamless user experience through background threading. As a result, users don’t have to wait for a task to complete to continue using the application.

Using background services and background threading, where appropriate, allows developers to avoid performance issues and provide players with a more enjoyable gaming experience.

What types of crashes happen when using background services and background threads? 

Background services and background threading are integral to many mobile applications but can also contribute to Unity crashes if mismanaged.

One common problem is that background threads can prevent the application from closing properly. To avoid this, developers should write their background threads in a task-oriented and finite manner. That way, the thread has a higher guarantee of completion.

Another issue with background threads is that they can lock the application into an ANR or orphaned app state. This happens when performing a long-running or resource-intensive operation, which prevents the user from interacting meaningfully within the app. For example, the UI could wait for a thread to finish retrieving data and have no back or cancel button visible. The user is then forced to restart the app, which causes frustration and a loss of their in-app progress.

It is essential to design background threads with proper task management and cancellation mechanisms to prevent these issues to ensure they do not run indefinitely and potentially block other processes. 

When using background services and background threads, developers should also be aware of the potential for various types of crashes that can occur at the hands of background threading issues. Below are three common types of crashes that can occur when using a background service or thread:

Resource contention

Resource contention happens when multiple threads access the same resource in a non-thread-safe way, resulting in conflicts and unexpected behavior in the application. To avoid this, developers should ensure all data interfaces between threads and services are thread-safe.

Hanging threads

Hanging threads are threads that will never finish or have run for an excessive time with no expected finish. This can cause the application to freeze or crash. To mitigate this issue, developers should write the service to be cancellable so that they can shut down the operation when they detect that it has exceeded a reasonable runtime.

Improper responses

Improper responses occur when a background thread returns a response that is not valid or expected by the application. To prevent this type of crash, developers should test the background thread thoroughly and have proper error handling and fallback mechanisms in place.

What is challenging about solving crashes related to background services and background threads?

These types of crashes can be more difficult to debug and control. Background services typically involve more complex interactions between threads and processes, and setting up appropriate synchronization or asynchronous communication can require more code and explicit management of state.

Another challenge posed by background services and background threads is that they can make it harder to reproduce and diagnose crashes. This is because background services and background threads often operate asynchronously and independently of the main user interface, so crashes may not be immediately visible to the developer. As a result, developers may need to rely more heavily on monitoring and diagnostic tools to identify and troubleshoot issues related to background services and background threads.

Overall, crashes related to background services and background threads require developers to be more vigilant and proactive in their monitoring and diagnostic efforts. Developers should be aware of the potential for crashes when using background services and background threads and take steps to ensure that their code is properly synchronized and that background threads are managed correctly. 

How can you prevent background services and background thread issues from crashing your Unity game?

First, write background threads in a task-oriented and finite manner, with a clear endpoint and reasonable timeout calls for APIs and background services. This prevents the thread from running indefinitely and consuming resources unnecessarily while allowing the developer to handle error conditions more gracefully.

Second, ensure that background threads are arbitrarily cancellable, especially for longer-running operations with an indeterminate end time. This allows you to shut down the operation when it has exceeded a reasonable runtime, preventing crashes and resource contention.

Third, make sure all data interfaces between threads and services are thread-safe. Non-thread-safe access to data can cause conflicts, crashes, or unexpected behavior in the application. Proper synchronization techniques should be used to ensure data is only accessed by one thread at a time to prevent resource contention and crashes. 

By following these steps, developers can prevent crashes caused by background services and background threading issues, which creates a smoother user experience for players.

What monitoring can you use to prevent background services and background threads from crashing your Unity game?

To prevent crashes related to background services or background threading in mobile games, developers need to take proactive measures. There are three measures that developers can enact. 

One option is using crash reporting tools to identify and diagnose the issue, enabling developers to fix problems before they become more severe. In addition, it’s also essential to consider the type of devices and operating systems the game will run on since crashes are more likely to occur on older or weaker devices or specific operating systems. Lastly, the features used within the service can also impact the likelihood of crashes, so developers must test their applications on various devices and operating systems and optimize them for background services and background threading. With careful planning and testing, developers can minimize crashes related to background services and deliver a more stable and reliable gaming experience to users.

Developers can use various tools and techniques to monitor and debug crashes related to background services and background threading. One common approach is to use comprehensive and observability monitoring tools like Embrace.

Embrace is a powerful tool that enables developers to monitor and diagnose background service metrics and threading issues in Unity games. By accessing logs and stack traces, developers can quickly pinpoint the problem’s root cause and identify the background service metric or thread causing issues. In addition, Embrace provides detailed performance data for each background service and thread, including the completion times and performance on varying devices and OS, and optimizes developer code. 

With its monitoring and diagnostic tools, Embrace can significantly reduce the number of crashes related to background services and threads by surfacing crashes across the foreground and background sessions, allowing developers to fix issues quickly. Embrace also offers features to optimize background service metrics and threads, such as identifying those that use too much CPU time or memory and reducing their impact on device performance and battery life.

Background services play a crucial role in mobile app development, but they can also be a source of crashes if not properly managed. However, with the proper monitoring and optimization strategies, developers can ensure that their background services and background threads run smoothly, enhancing the user experience and reducing the risk of crashes and other performance problems.

Unity developers must prioritize monitoring and testing for their background services and background threads to ensure their games run smoothly for all users. Embrace’s SDK for Unity is an excellent tool for developers looking to explore monitoring options for their games. Explore Embrace and keep your Unity game running smoothly for all players.

Embrace Deliver incredible mobile experiences with Embrace.

Get started today with 1 million free user sessions.

Get started free

Build better mobile apps with Embrace

Find out how Embrace helps engineers identify, prioritize, and resolve app issues with ease.