編集:iOS8から始めて、AppleはPushKitフレームワークを導入して、VoIPアプリケーションを構成するために必要な作業をリリースし、エネルギー使用量も削減します. あなたは本当にそれに移行する必要があります
VoIP アプリを開発するためのヒントがあります。Appleからのリファレンスです。
ボイス オーバー インターネット プロトコル (VoIP) アプリを使用すると、ユーザーはデバイスのセルラー サービスの代わりにインターネット接続を使用して電話をかけることができます。このようなアプリは、関連するサービスへの永続的なネットワーク接続を維持して、着信通話やその他の関連データを受信できるようにする必要があります。システムは、VoIP アプリを常に起動しておくのではなく、一時停止できるようにし、ソケットを監視する機能を提供します。着信トラフィックが検出されると、システムは VoIP アプリを起動し、ソケットの制御をアプリに返します。
VoIP アプリを実装するには、いくつかの要件があります。
- アプリの Voice over IP バックグラウンド モードを有効にします。(VoIP アプリには音声コンテンツが含まれるため、Audio および AirPlay バックグラウンド モードも有効にすることをお勧めします。) Xcode プロジェクトの [機能] タブでバックグラウンド モードを有効にします。
- アプリのソケットの 1 つを VoIP 用に構成します。
- バックグラウンドに移行する前に、setKeepAliveTimeout:handler: メソッドを呼び出して、定期的に実行されるハンドラーをインストールします。アプリはこのハンドラーを使用して、サービス接続を維持できます。
- アクティブな使用への移行とアクティブな使用からの移行を処理するようにオーディオ セッションを構成します。
- iPhone でのユーザー エクスペリエンスを向上させるには、Core Telephony フレームワークを使用して、セルベースの通話に関する動作を調整します。コア テレフォニー フレームワーク リファレンスを参照してください。
- VoIP アプリの良好なパフォーマンスを確保するには、システム構成フレームワークを使用してネットワークの変更を検出し、アプリが可能な限りスリープ状態になるようにします。
VoIP バックグラウンド モードを有効にすると、システムは、ネットワーク ソケットを管理するために、必要に応じてアプリをバックグラウンドで実行できるようにする必要があることを認識できます。このキーを使用すると、アプリでバックグラウンド オーディオを再生することもできます (ただし、オーディオと 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 サービス接続を維持するために使用されるソケットを含む、すべてのソケットも解放されます。したがって、アプリが起動されると、常にソケットを最初から作成する必要があります。
ここにサンプル プロジェクトを作成し、関連するサーバー側コードをここに作成しました。