Some features of the implementation of background applications for iOS 4
The article will discuss the experience of implementing background applications for the iOS 4 platform as part of the work on the Viber project of Viber Inc. The first version of Viber was available to AppStore users on December 2, 2010. The number of users of the Viber application for iPhone in May 2011 exceeded 15 million users. The application has several interesting features:
The version for the Android operating system is now in a closed beta test.
Prior to the release of iOS 4, iPhone app developers did not have the ability to complete tasks in the background and maintain a constant connection with the server to quickly notify users of events and update information for an application that is not currently running. The only limited way to notify users of events from the server was the push notification mechanism, which has the following disadvantages:
Apple has implemented support for background task execution in the iOS 4 operating system. When implementing background task execution, the application developer is faced with significant difficulties, the solution of which can be found mainly empirically with the hints of official Apple documentation.
In a series of articles, it is planned to talk about ways to solve various problems associated with performing tasks in the background when developing applications for the iOS 4 platform that have been found experimentally. This article will discuss the basic issues of performing tasks in the background using one of the three types of platform background applications iOS 4 voip .
In iOS 4, three types of background applications are available (they can be used in the application at the same time):
The developers have another new opportunity related to the background execution of tasks: sending local notifications. The notification itself is very similar to remote push, but does not require a connection to the server and is sent by the application to itself. At the same time, the application currently running in the background can send such a notification immediately to attract the attention of the user. For an application in the background, sending a local notification may be the only way to get the user's attention. A local notification may be a direction by the application at a predetermined time and / or at a certain interval. When sending a local notification, the application itself can be turned off (for example, an alarm / timer). The maximum number of active application notifications cannot exceed 128 active notifications in the queue.
Let us consider in more detail some features of using the background class voip. First of all, it is the ability to constantly connect to the server to obtain relevant information about incoming calls and messages or other events that need to be reported to the user. As practice shows, the efficiency of remote push is often not enough. Only one tcp socket can be used to communicate with the server in the background, which is specially marked for iOS before returning from the applicationDidEnterBackground function :. In this case, the application will be suspended, but the system will allocate time slices for operation in 3 cases: a) when incoming data appears on the socket; b) when changing the network properties that affect the availability of the server to which the socket is connected; c) by timer in the code block set as the keep-alive handler, the minimum keep-alive interval is 10 minutes. You can use local notifications to capture user attention while processing these events.
In addition to maintaining server communication in the background, the voip class provides another important opportunity: any application with the voip class in the parameters will automatically start in the background at the start of the system and restart in the background after crashes. An important feature is that when launched in the background, the UIApplicationDelegate applicationDidEnterBackground method :it will not be called, so you need to connect and mark the socket as VoIP before returning from the application: didFinishLaunchingWithOptions: method , otherwise the application will simply be suspended.
In order to make iOS understand which connection needs to be monitored in the background, there are several possibilities depending on which of the network APIs is used. In the case of the highest-level NSMutableURLRequest, just call the setNetworkServiceType method for it :with the NSURLNetworkServiceTypeVoIP parameter. If the work goes at the NSInputStream / NSOutputStream level, then you need to set the NSStreamNetworkServiceTypeVoIP value for the NSStreamNetworkServiceType property. In our application, the network layer is written to support the maximum number of platforms, so regular BSD sockets are used. There is no API for configuring BSD sockets as voip, so you need to create a pair of streams from an already connected socket using CFStreamCreatePairWithSocket and then set the kCFStreamNetworkServiceType property of the streams to kCFStreamNetworkServiceTypeVoIP.
The voip socket configuration must be completed before returning from the application: didFinishLaunchingWithOptions: and applicationDidEnterBackground methods :(as well as before returning from the keep-alive handler or changing the network properties if it reconnected to the server), so you need to use synchronous APIs to connect, which is often inconvenient, or connect to the server and configure the voip socket in a separate thread, and block the main thread until the connection is completed. The easiest way to synchronize in this case is to use NSConditionLock. This is a high-level interface for posix conditional variables, which is much easier to use. A simple NSLock or posix mutex cannot be used, since it must be blocked in one thread and unlocked in another. Example connection code in the background:
The voip background execution class will be useful for any application that needs to notify the user of events from the server in a timely manner or to accumulate relevant information that is not necessarily related to VoIP telephony.
In the next article, we will consider in more detail the keep-alive handlers and network state changes, how to correctly calculate the connection timeout, and also touch on the sound playing in the background.
- repeats the iPhone phonebook interface;
- builds a social graph based on the user's phone book;
- Allows you to call and send short messages between Viber users.
The version for the Android operating system is now in a closed beta test.
Introduction
Prior to the release of iOS 4, iPhone app developers did not have the ability to complete tasks in the background and maintain a constant connection with the server to quickly notify users of events and update information for an application that is not currently running. The only limited way to notify users of events from the server was the push notification mechanism, which has the following disadvantages:
- slow delivery of notifications, because Apple’s intermediate servers are used with a possible delay of several minutes, which is unacceptable when notifying a user of incoming calls to a VoIP application;
- a small (256 bytes) amount of information that can be transmitted in a notification;
- When a user cancels a push notification, the application does not receive data from the notification.
Apple has implemented support for background task execution in the iOS 4 operating system. When implementing background task execution, the application developer is faced with significant difficulties, the solution of which can be found mainly empirically with the hints of official Apple documentation.
In a series of articles, it is planned to talk about ways to solve various problems associated with performing tasks in the background when developing applications for the iOS 4 platform that have been found experimentally. This article will discuss the basic issues of performing tasks in the background using one of the three types of platform background applications iOS 4 voip .
In iOS 4, three types of background applications are available (they can be used in the application at the same time):
- voip , designed for applications that allow you to make phone calls over the Internet;
- audio , allows you to record and play sound, including over the network and through AirPlay;
- location , allows you to get location data. To tell the operating system that the application supports background execution, you must add a line to the types, suggesting the background tasks (voip, audio, location) in an array UIBackgroundModes file the Info.plist .
The developers have another new opportunity related to the background execution of tasks: sending local notifications. The notification itself is very similar to remote push, but does not require a connection to the server and is sent by the application to itself. At the same time, the application currently running in the background can send such a notification immediately to attract the attention of the user. For an application in the background, sending a local notification may be the only way to get the user's attention. A local notification may be a direction by the application at a predetermined time and / or at a certain interval. When sending a local notification, the application itself can be turned off (for example, an alarm / timer). The maximum number of active application notifications cannot exceed 128 active notifications in the queue.
Background voip class
Let us consider in more detail some features of using the background class voip. First of all, it is the ability to constantly connect to the server to obtain relevant information about incoming calls and messages or other events that need to be reported to the user. As practice shows, the efficiency of remote push is often not enough. Only one tcp socket can be used to communicate with the server in the background, which is specially marked for iOS before returning from the applicationDidEnterBackground function :. In this case, the application will be suspended, but the system will allocate time slices for operation in 3 cases: a) when incoming data appears on the socket; b) when changing the network properties that affect the availability of the server to which the socket is connected; c) by timer in the code block set as the keep-alive handler, the minimum keep-alive interval is 10 minutes. You can use local notifications to capture user attention while processing these events.
In addition to maintaining server communication in the background, the voip class provides another important opportunity: any application with the voip class in the parameters will automatically start in the background at the start of the system and restart in the background after crashes. An important feature is that when launched in the background, the UIApplicationDelegate applicationDidEnterBackground method :it will not be called, so you need to connect and mark the socket as VoIP before returning from the application: didFinishLaunchingWithOptions: method , otherwise the application will simply be suspended.
In order to make iOS understand which connection needs to be monitored in the background, there are several possibilities depending on which of the network APIs is used. In the case of the highest-level NSMutableURLRequest, just call the setNetworkServiceType method for it :with the NSURLNetworkServiceTypeVoIP parameter. If the work goes at the NSInputStream / NSOutputStream level, then you need to set the NSStreamNetworkServiceTypeVoIP value for the NSStreamNetworkServiceType property. In our application, the network layer is written to support the maximum number of platforms, so regular BSD sockets are used. There is no API for configuring BSD sockets as voip, so you need to create a pair of streams from an already connected socket using CFStreamCreatePairWithSocket and then set the kCFStreamNetworkServiceType property of the streams to kCFStreamNetworkServiceTypeVoIP.
The voip socket configuration must be completed before returning from the application: didFinishLaunchingWithOptions: and applicationDidEnterBackground methods :(as well as before returning from the keep-alive handler or changing the network properties if it reconnected to the server), so you need to use synchronous APIs to connect, which is often inconvenient, or connect to the server and configure the voip socket in a separate thread, and block the main thread until the connection is completed. The easiest way to synchronize in this case is to use NSConditionLock. This is a high-level interface for posix conditional variables, which is much easier to use. A simple NSLock or posix mutex cannot be used, since it must be blocked in one thread and unlocked in another. Example connection code in the background:
// Состояния блокировки
enum {
EConnecting,
EConnected,
};
// Объявление переменной, хранящей блокировку
NSConditionLock * waitForConnectionLock = nil;
// Код подключения, вызываемый из методов
// application:didFinishLaunchingWithOptions:, applicationDidEnterBackground:
// и обработчика keep-alive в главном потоке
waitForConnectionLock = [[NSConditionLock alloc] initWithCondition:EConnecting];
// Запускаем подключение к серверу в отдельном потоке
[server performSelectorInBackground:@selector(connect) withObject:waitForConnectionLock];
// Выполняем другую необходимую работу
…
// Пытаемся захватить блокировку со статусом EConnected до тайм-аута
// Подробнее о значении тайм-аута далее
if ([waitForConnectionLock lockWhenCondition:EConnected beforeDate:timeout]) {
[waitForConnectionLock unlock];
// Блокировка получена до тайм-аута, значит, подключение успешно, можно пометить
// сокет как voip
[server markSocketAsVoIP];
}
// удаляем блокировку
[waitForConnectionLock release];
// Можно возвращать управление системе
return;
//-----------------
// Код метода connect
// Захватываем блокировку, ее статус нас не интересует, он может быть только EConnecting
[waitForConnectionLock lock];
// Подключаемся к серверу любым способом
…
// Если подключение успешно, освобождаем блокировку со статусом EConnected
// Код в главном потоке сможет ее захватить
[waitForConnectionLock unlockWithCondition:EConnected];
The voip background execution class will be useful for any application that needs to notify the user of events from the server in a timely manner or to accumulate relevant information that is not necessarily related to VoIP telephony.
Conclusion
In the next article, we will consider in more detail the keep-alive handlers and network state changes, how to correctly calculate the connection timeout, and also touch on the sound playing in the background.