现在的位置: 首页 > 综合 > 正文

VOIP 以及后台程序相关

2013年02月04日 ⁄ 综合 ⁄ 共 5986字 ⁄ 字号 评论关闭

必须成对出现的两个函数,而且,就在快要结束前的evnts handler 中调用后者

m_bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{

    [[UIApplication sharedApplication] endBackgroundTask:m_bgTask];

    m_bgTask = UIBackgroundTaskInvalid;

=====beginBackgroundTaskWithExpirationHandler:

- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handleriOS (4.0 and later)Marks the beginning of a new long-running background task.handler: A handler to be called shortly before the application’s remaining background
time reaches 0.

A unique identifier for the new background task.

endBackgroundTask:

Marks the end of a specific long-running background task.

- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier
Parameters
identifier

An identifier returned by the beginBackgroundTaskWithExpirationHandler: method.

Discussion

You must call this method to end a task that was started using thebeginBackgroundTaskWithExpirationHandler: method. If you do not, the system may kill your application.

This method can be safely called on a non-main thread.

Availability
  • Available in iOS 4.0 and later.

========

My App Requirement: I should maintain a socket connection to trigger local notification on server push without
using Push Notification(APNs) for some reasons. So i'm using the VOIP background capability of iphone to maintain socket connection.

1. I have configured a stream for VOIP in order to persist socket connection to run in background, so what Timeout value should
i set?, will the socket connection terminates once the timeout expires?, how do i make my application to listen to the socket all the time.?

Client stream configuration is as follows,

    NSString *urlStr = @"http://192.168.0.108";
    NSURL *website = [NSURL URLWithString:urlStr];
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 1234, &readStream, &writeStream);

    CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
    CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);    

    NSInputStream *inputStream = (NSInputStream *)readStream;
    NSOutputStream *outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
    [outputStream setDelegate:self];
    [outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];

2. should i reconnect the stream in the handler applicationDidEnterBackground:

   [[UIApplication sharedApplication] setKeepAliveTimeout:86400 handler:^(void) 
{

    if (inputStream)
        [inputStream close];
    if (outputStream)
        [outputStream close];


    urlStr = @"http://192.168.0.108";
    website = [NSURL URLWithString:urlStr];
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 1234, &readStream, &writeStream);
    CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
    CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);    
    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
    [outputStream setDelegate:self];
    [outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];

    }];

3. Say My server restarts and the app is in background how do i ensure the connection? If the Wi-Fi connection
in my iphone or if i terminate the server app the connection will be closed, so what measures should i take to make my app work as expection?

You also need to ensure that you have set the in your pList file

<key>UIBackgroundModes</key>
<array>
    <string>voip</string>
</array>

The socket will be managed by the iOS while your application is in the background. Your application will receive the CPU time as soon there is a data available in the socket. So in the runLoop I am checking ht

In my case the signaling protocol is working in a separate thread, so I am spinning the runLoop my self

  // Start runloop
  while (!m_needStop) 
  {
    CFRunLoopRun();
  }

And stopping it when needed:

  m_needStop = true;
  {
    QAutoLock l(m_runLoopGuard);
    if ( m_runLoop != NULL )
      CFRunLoopStop(m_runLoop);
  }

For the sockets in runLoop I have setup the handler functions before scheduling them into the runLoop:

  int nFlags = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
  CFStreamClientContext context;
  context.info = this;
  context.version = 0;
  context.release = NULL;
  context.retain = NULL;
  context.copyDescription = NULL;

  if ( !CFReadStreamSetClient(m_readStream, nFlags, NotificationProtocolHandler::ReadStreamCallback, &context) )
  {
    ReleaseStreams();
    return false;
  }

  if ( !CFWriteStreamSetClient(m_writeStream, nFlags, NotificationProtocolHandler::WriteStreamCallback, &context) )
  {
    ReleaseStreams();
    return false;
  }

These are the functions which will be called when your socket will has some info for you and even if your application in the background:

void NotificationProtocolHandler::ReadStreamCallback(CFReadStreamRef stream,
                                                     
CFStreamEventType eventType,
                                                     
void *clientCallBackInfo)
{      
 
NotificationProtocolHandler* handler = (NotificationProtocolHandler*)clientCallBackInfo;
 
switch (eventType)
 
{
   
case kCFStreamEventOpenCompleted:
     
break;

    case kCFStreamEventHasBytesAvailable:
      handler
->ProcessInput();
     
break;

    case kCFStreamEventErrorOccurred:
      handler
->ProcessConnectionError();
     
break;

    case kCFStreamEventEndEncountered:
      handler
->ProcessConnectionError();
     
break;

    default:
     
break; // do nothing
 
}
}

void NotificationProtocolHandler::WriteStreamCallback(CFWriteStreamRef stream,
                                                     
CFStreamEventType eventType,
                                                     
void *clientCallBackInfo)
{
 
NotificationProtocolHandler* handler = (NotificationProtocolHandler*)clientCallBackInfo

抱歉!评论已关闭.