21

iOS アプリケーションのバックグラウンドで実行する VOIP ソケットを取得しています。

接続は正常に機能しますが、アプリがバックグラウンドに移行しても復帰しません。ただし、アプリを再度開くと、スリープ中に受け取ったメッセージに応答します。

ストリームを次のように設定しました。

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
                                   (CFStringRef) @"test.iusealocaltestserver.com",
                                   5060,
                                   &myReadStream,
                                   &myWriteStream);
CFReadStreamSetProperty (    myReadStream,
                             kCFStreamNetworkServiceType,
                             kCFStreamNetworkServiceTypeVoIP
                             );

CFSocketNativeHandle native;
CFDataRef nativeProp = CFReadStreamCopyProperty(myReadStream, kCFStreamPropertySocketNativeHandle);

CFDataGetBytes(nativeProp, CFRangeMake(0, CFDataGetLength(nativeProp)), (UInt8 *)&native);
CFRelease(nativeProp);

CFSocketRef theSocket = CFSocketCreateWithNative(kCFAllocatorDefault, native, 0, NULL, NULL);

CFSocketGetContext(theSocket,&theContext);    


CFOptionFlags readStreamEvents = kCFStreamEventHasBytesAvailable | 
kCFStreamEventErrorOccurred     |
kCFStreamEventEndEncountered    |
kCFStreamEventOpenCompleted;

CFReadStreamSetClient(myReadStream,
                           readStreamEvents,
                           (CFReadStreamClientCallBack)&MyCFReadStreamCallback,
                      (CFStreamClientContext *)(&theContext));

CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(),
                                kCFRunLoopCommonModes);

次に、コールバックは次のように設定されます。

static void MyCFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *pInfo);

static void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSLog(@"Callback Happened");

   [pool release];
}

データを受信し、アプリが開いているときに「Callback Happened」が呼び出されますが、アプリが最小化されている場合は呼び出されません。ただし、アプリが再起動すると、最小化中に受信したすべてのデータが処理されます。

info.plist に voip タグを追加しました。私の CFReadStreamSetProperty は true を返します。シミュレーターではなくデバイスで実行しています。それでもうまくいかないので、何が問題なのかわかりません。ばかげたことをしただけかもしれませんが、オンラインでコードをチェックできるものはほとんどありません。

編集:このプロジェクトに取り組んでおらず、mac/iOs sdk にアクセスできないため、回答をテストできません。同様の問題を抱えている人が以下の回答のいずれかが役立つと感じた場合は、お知らせください。ベストアンサーに投票します。

4

5 に答える 5

29

plistファイルの基本設定を除いて、VOIPアプリケーションをバックグラウンドで実行したい場合は、プロパティがVOIPに設定されているTCPソケットが必要です。アプリケーションがバックグラウンドに入ると、iOSシステムがこのソケットを処理します。 TCPソケットを除いて、すべてが「スリープ」でした。また、VOIP サーバーが TCP ソケットと考えられるデータを送信すると、アプリケーションは 10 秒間起動します。この間、ローカル通知を投稿できます。

VOIPソケットとして設定できるのはTcpソケットのみです。しかし、私が知っているように、ほとんどの VOIP アプリケーションは UDP ソケットに基づいています。コントロールソケットをデータソケットから分離したくない場合。アプリケーションの「起動」に焦点を当てた別の tcp ソケットを作成する必要があります。私の個人的な経験から、この「起動」信号と実際の sip 制御信号の同期を維持することは非常に難しく、アプリケーションは常に sip 招待要求を逃します。

したがって、最善の方法は、sip コントロール シングルを UDP データ ソケットから分離し、それを tcp ソケットにすることです。これが最良の解決策ですが、tcp ソケットを使用して音声データを転送しないでください。

もう 1 つの汚れた方法: アプリケーションを常に起動しておくことです。私が言ったように、アプリケーションが受信した各TCPシングルは、「VOIP」tcpソケットがアプリケーションを10秒間目覚めさせ続けると考えていたため、この期間の終わり(9秒後)に、サーバーに応答を送信して要求することができます別の信号、次の信号が到着すると、アプリケーションは再び起動し、9 秒後に再度応答を送信します。これを続けると、アプリケーションは永久に起動します。

于 2011-09-12T19:44:19.197 に答える
5

私はまったく同じシナリオで立ち往生していました。
私の問題は、複数のソケットを Voip ソケットとして構成したことです。

Apple の voip に関するドキュメントで、「VoIP を使用するためにアプリケーションのソケットの1 つ
を 構成する」と書か れているのを見ることができます。

単一のソケットに従ってアプリを起動しているだけだと思います。

言及されている他のすべてのものはまだ正しいです:

  • kCFStreamNetworkServiceTypeVoIP
  • 'info.plist' UIBackgroundModes: voip、オーディオ
  • 'info.plist' UIRequiresPersistentWifi キー
  • シミュレーターでは機能しません
于 2011-08-14T13:45:04.090 に答える
3

私も同じ問題に直面しています。しかし、私の場合、ネットワークの変更が発生しない限り、すべてが正常に機能しています。ネットワークの変更を検出するために、アップルの「到達可能性」クラスを使用しました。アプリがバックグラウンドにある場合、ネットワークを次のように手動で切り替えても、ソケットが機能していることがあります。

  1. Wi-Fi -> 3G
  2. 3g -> Wi-Fi

しばらくしてから、手動でネットワークを切り替えようとしているとしましょう。アプリがネットワークの変更を検出していないようです。以下のアップルドキュメントを読みました。私は間違っていると確信しています(または)ステップ3と6を理解していません。

VoIP アプリを実装するには、いくつかの要件があります。

1. UIBackgroundModes キーをアプリの Info.plist ファイルに追加します。このキーの値を、voip 文字列を含む配列に設定します。

  1. アプリのソケットの 1 つを VoIP 用に構成します。

  2. バックグラウンドに移行する前に、setKeepAliveTimeout:handler: メソッドを呼び出して、定期的に実行されるハンドラーをインストールします。アプリはこのハンドラーを使用して、サービス接続を維持できます。

  3. アクティブな使用への移行とアクティブな使用からの移行を処理するようにオーディオ セッションを構成します。

5. iPhone でのユーザー エクスペリエンスを向上させるには、コア テレフォニー フレームワークを使用して、セルベースの通話に関する動作を調整します。コア テレフォニー フレームワーク リファレンスを参照してください。

  1. VoIP アプリの良好なパフォーマンスを確保するには、システム構成フレームワークを使用してネットワークの変更を検出し、アプリが可能な限りスリープ状態になるようにします。
于 2012-08-30T15:16:07.093 に答える
0

Info.plist で設定する必要がある<key>UIBackgroundModes</key><array><string>audio</string></array>場合があり、アプリを切り替える前に、オーディオ セッションがアクティブ/実行中/その他であることを確認する必要があります (前提として、アプリを使用しているときに、突然録音/音楽の再生を開始しないことを前提としています)。背景にあります)。

ドキュメントによると、「オーディオ」を使用するとバックグラウンドでオーディオを再生できますが、おそらくこれはオーディオの録音にも当てはまります。うまくいかない場合は、次の方法を試してみてください。

  • 「voip」と「audio」の両方を設定します。
  • 無音を再生します (これは、Audio Queue API を使用するのが最も簡単かもしれません)。
于 2011-07-28T21:38:36.780 に答える
-1

アプリケーション デリゲートに「applicationDidEnterBackground:」がありますか。バックグラウンドモードをサポートしていることを認識するには、ios用に定義する必要があることをどこかで読んだことがあると確信しています。何も実装する必要はありません。

例えば

- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
于 2011-08-15T10:24:24.647 に答える