GCDAsyncSocket background VOIP

2019-03-14 04:38发布

I'm trying to implement this(Configuring Sockets for VoIP Usage) using this(CocoaAsyncSocket). To the best of my knowledge step 1 I have done, adding VOIP to background services in the plist, and below should be step 2 (Configure one of the app’s sockets for VoIP usage)

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)connectedPort
{
    [CCV setLocalMode:FALSE];

    [socket performBlock:^{
                 [socket enableBackgroundingOnSocket];
             }];

But the rest of the steps I cannot figure out. If I do

- (void)applicationDidEnterBackground:(UIApplication *)application
{
     expirationHandler = ^{

          [app endBackgroundTask:bgTask];
          bgTask = UIBackgroundTaskInvalid;


          bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
     };

     bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];


     // Start the long-running task and return immediately.
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

          while (1) {
               sleep(1);               
               //NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);

               if ([rootViewController isIncomingCall] && showedCall != TRUE) {
                    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
                    if (localNotif) {
                         localNotif.alertBody = [NSString stringWithFormat:@"Incoming Call."];
                         localNotif.alertAction = NSLocalizedString(@"Accept Call", nil);
                         localNotif.soundName = @"alarmsound.caf";
                         //                         localNotif.applicationIconBadgeNumber = 1;
                         [application presentLocalNotificationNow:localNotif];
                         [localNotif release];
                    }
                    showedCall = TRUE;
               }
          }  
     });      

}

My client will listen for 10mins then stop. I need to do 2 things: watch for a specific (incoming call) data packet, and send a keepalive every 5seconds. But I dont see where these things are to be configured at. Furthermore the definition on the apple link above states "To prevent the loss of its connection, a VoIP app typically needs to wake up periodically and check in with its server. To facilitate this behavior, iOS lets you install a special handler using the setKeepAliveTimeout:handler: method of UIApplication" From my understanding of that this timeout thing should only be doing the keepalive, however that doesnt make sense because the minimal time is 600seconds? And like I said above I cannot find where I tell it what packet to look for as well as what to do when its found.

2条回答
The star\"
2楼-- · 2019-03-14 05:29

I realise this is an old question now - but you should call

 BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
 if (backgroundAccepted)
 {
      NSLog(@"VOIP backgrounding accepted");
 }

On app startup and use it all the time - the reason is, as you'll discover, is when the app is foregrounded, but the screen is LOCKED you don't receive the didEnterBackground call, and your app will be put to sleep 10-15 mins after the screen has locked, even though you are foregrounded

查看更多
叛逆
3楼-- · 2019-03-14 05:30

so i believe i have resolved the issue but need further testing to be 100% sure. Currently i ran a test with this code for the length of 21mins of suspended time and it worked

step 2:

 [socket performBlock:^{
                 [socket enableBackgroundingOnSocket];
             }];

step 3:

- (void)applicationDidEnterBackground:(UIApplication *)application {

     inProgram = FALSE;
     showedCall = FALSE;

     BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
     if (backgroundAccepted)
     {
          NSLog(@"VOIP backgrounding accepted");
     }

}

this seems to keep my client running so from here i add an observer to wait for my incoming call packet and launch a notification when that packet is seen

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{  
     if ([keyPath isEqualToString:@"currentDigitalJoin"]) 
     {
          switch ([[cClient currentDigitalJoin]intValue]) 
          {  
               case 1000: 
               {   
                    if (showedCall != TRUE && inProgram != TRUE) {
                         NSLog(@"incoming audio call");
                         UILocalNotification *localNotif = [[UILocalNotification alloc] init];
                         if (localNotif) {
                              localNotif.alertBody = [NSString stringWithFormat:@"Incoming Call."];
                              localNotif.alertAction = NSLocalizedString(@"Accept Call", nil);
                              localNotif.soundName = @"alarmsound.caf";
                              [app presentLocalNotificationNow:localNotif];
                              [localNotif release];
                              showedCall = TRUE;
                         }
                    }
                    break;
               }
               case 602: 
               {   
                    if (showedCall != TRUE && inProgram != TRUE) {
                         NSLog(@"incoming audio call");
                         UILocalNotification *localNotif = [[UILocalNotification alloc] init];
                         if (localNotif) {
                              localNotif.alertBody = [NSString stringWithFormat:@"Incoming Call."];
                              localNotif.alertAction = NSLocalizedString(@"Accept Call", nil);
                              localNotif.soundName = @"alarmsound.caf";
                              [app presentLocalNotificationNow:localNotif];
                              [localNotif release];
                              showedCall = TRUE;
                         }
                    }
                    break;
               }
               case 513: 
               {   
                    showedCall = FALSE;
                    break;
               }
          }
     }else if([keyPath isEqualToString:@"currentDigitalJoin"])
     {
          switch ([[cClient currentDigitalJoin]intValue]) 
          { 
               case 602: 
               {   
                    showedCall = FALSE;
                    break;

               }               
          }
     }
}

NOTE: the "step"s indicated are in reference to the steps indicated on the apple documentation

also dont forget to set the require wireless in the plist file

查看更多
登录 后发表回答