Настройка приложения iOS VoIP для работы в спящем / фоновом режиме
Я разрабатываю приложение для iOS (7.1) на основе VoIP. Это базовое сокетное программирование написано на C++, а не на цели C. Приложение отлично работает на переднем плане, но при переводе в спящий / фоновый режим оно не может получать никаких сообщений от сервера. Согласно документу Apple, мы должны настроить один из сокетов приложения для использования VoIP. Я не могу понять, как настроить сокеты C++ (потому что есть много сокетов; т.е. SSL, SIP, RESTful).
Намерение состоит в том, чтобы запустить приложение в спящем режиме, пока оно не будет убито. Пробовал несколько ссылок и даже пару из них от SO, но, поскольку я новичок, я бы хотел иметь пошаговую процедуру для этой конфигурации. [Примечание: где-то я нашел платформу CoreFoudation, нужно ли мне это использовать?]
2 ответа
Редактировать: начиная с iOS8, Apple представляет платформу PushKit, чтобы выпустить работу, которую мы должны сделать, чтобы настроить приложение VoIP, и это также уменьшает потребление энергии. Вам действительно нужно перейти на него
Есть советы по разработке приложения VoIP, ссылка от Apple
Приложение для передачи голоса по Интернет-протоколу (VoIP) позволяет пользователю совершать телефонные звонки, используя подключение к Интернету вместо услуги сотовой связи устройства. Такое приложение должно поддерживать постоянное сетевое соединение со связанной с ним службой, чтобы оно могло принимать входящие вызовы и другие соответствующие данные. Вместо того чтобы постоянно поддерживать бодрствование VoIP-приложений, система позволяет им приостанавливаться и предоставляет средства для мониторинга их сокетов. При обнаружении входящего трафика система активирует приложение VoIP и возвращает ему управление своими сокетами.
Существует несколько требований для реализации приложения VoIP:
- Включите фоновый режим Voice over IP для вашего приложения. (Поскольку в приложениях VoIP используется аудиоконтент, рекомендуется также включить фоновый режим Audio и AirPlay.) Фоновые режимы включаются на вкладке "Возможности" проекта XCode.
- Настройте один из сокетов приложения для использования VoIP.
- Прежде чем перейти к фону, вызовите метод setKeepAliveTimeout:handler: для установки обработчика, который будет выполняться периодически. Ваше приложение может использовать этот обработчик для поддержания своего сервисного соединения.
- Сконфигурируйте ваш аудио сеанс для обработки переходов в активное использование и из него.
- Чтобы обеспечить лучшее взаимодействие с пользователем на iPhone, используйте платформу Core Telephony для настройки вашего поведения в отношении телефонных звонков на сотовой основе; см. Базовую Ссылку Платформы телефонии.
- Чтобы обеспечить хорошую производительность для вашего VoIP-приложения, используйте инфраструктуру конфигурации системы, чтобы обнаружить изменения в сети и позволить вашему приложению как можно дольше спать.
Включение фонового режима VoIP позволяет системе знать, что оно должно позволять приложению работать в фоновом режиме по мере необходимости для управления сетевыми сокетами. Эта клавиша также позволяет вашему приложению воспроизводить фоновое аудио (хотя включение режимов Audio и AirPlay по-прежнему рекомендуется). Приложение, поддерживающее этот режим, также запускается в фоновом режиме сразу после загрузки системы, чтобы обеспечить постоянную доступность служб VoIP.
Код ниже показывает, как настроить сокет приложения для использования VoIP.
Шаг 1: подключиться к серверу
uint16_t port ;
NSString *strIp ;
char ip[20] = {0} ;
memset(ip, 0, sizeof(ip)) ;
memcpy(ip, [strIp UTF8String], [strIp length]) ;
clientSocket = socket(AF_INET, SOCK_STREAM, 0) ;
struct sockaddr_in server_addr ;
bzero(&server_addr, sizeof(server_addr)) ;
server_addr.sin_port = htons(port) ;
server_addr.sin_addr.s_addr = inet_addr(ip) ;
server_addr.sin_family = AF_INET ;
int i = connect(clientSocket, (const struct sockaddr *)&server_addr, sizeof(server_addr)) ;
if (i >= 0) {
}
Код на стороне сервера может быть в среде C++, но вы можете передать clientSocket
к примеру Objective-C, это int
значение.
Шаг 2: Создать и настроить поток чтения и записи
После подключения к серверу необходимо создать поток для чтения и записи на основе clientSocket
с помощью CFStreamCreatePairWithSocket()
и установить свойство потоков с NSStreamNetworkServiceTypeVoIP
,
Определите потоки чтения и записи и сохраняйте сильные ссылки на них. Закройте и отпустите их, когда соединение потеряно.
@property (nonatomic, strong) NSInputStream *inputStream ;
@property (nonatomic, strong) NSOutputStream *outputStream ;
Затем настройте потоки:
CFReadStreamRef readStreamRef = nil ;
CFWriteStreamRef writeStreamRef = nil ;
CFStreamCreatePairWithSocket(NULL, clientSocket, &readStreamRef, &writeStreamRef) ; // the socket must have already been connected.
_inputStream = (__bridge_transfer NSInputStream *)readStreamRef ;
_outputStream = (__bridge_transfer NSOutputStream *)writeStreamRef ;
[_inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[_outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[_inputStream open] ;
[_outputStream open] ;
Убедитесь, что сокет уже подключен, прежде чем соединяться с потоком чтения и записи.
Шаг 3: сохранить связь
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
// the code to check if the socket is connected to server
// if not, reconnect to server
// and re-set the read stream and write stream in step2
}] ;
Когда ваше приложение входит в фоновый режим, сокет управляется системой, и когда сервер отправляет пакет вашему приложению, система запускает его и передает пакет ему. У вас есть всего несколько секунд, чтобы обработать данные, так что не делайте здесь много работы. Поскольку это приложение VoIP, сокет должен использоваться для уведомления пользователя о входящем вызове, и вы можете нажать локальное уведомление, чтобы пользователь знал об этом.
Поскольку приложения VoIP должны оставаться запущенными, чтобы принимать входящие вызовы, система автоматически перезапускает приложение, если оно завершается с ненулевым кодом выхода. (Этот тип выхода может произойти, когда имеется нехватка памяти, и в результате ваше приложение завершается.) Однако при завершении работы приложения также освобождаются все его сокеты, включая тот, который используется для поддержания соединения службы VoIP. Поэтому, когда приложение запускается, оно всегда должно создавать свои сокеты с нуля.
Я создал пример проекта здесь, соответствующий код на стороне сервера здесь.
Помимо настройки сокета необходимо внести некоторые изменения в файл Info.plist приложения iOS, в котором необходимо указать voip
фоновый режим.
Более подробную информацию можно найти здесь: Apple Dev Documentation