Disable WiFi from Multi Peer Connectivity

余生颓废 提交于 2019-12-11 04:06:40

问题


I have gone over the documentation, but there isn't much information on Multipeer Connectivity related to choosing a possible medium for peers to connect.

Multipeer Connectivity automatically discovers peers based on WiFi, or Bluetooth. Is there a way to limit this to only Bluetooth?


回答1:


As @kdogisthebest correctly states, there's no way to force Multipeer Connectivity to use a particular network technology, but as your question relates to a particular problem with WiFi, this answer details what I'm doing to work around that.

I've worked around the issue of 'phantom' peers over WiFi by sending a shortened timestamp in the discoveryInfo when creating the MCNearybyServiceAdvertiser. There are several caveats here:

1) This solution assumes both devices have the same time. I ensure this by using a modified version of ios-ntp as the app's time source.

2) It also assumes that Advertising and Browsing do not run for too long. I have a set length of 60 seconds for discovery phases, and I completely re-init the browser/advertiser on each restart.

3) MPC doesn't seem to like too many bytes in the discoveryInfo so sending an NSTimeInterval based on epoch doesn't work. I had to truncate them.

So when my app enters discovery mode, it starts browsing and advertising simultaneously. The advertising code looks like:

- (void)startAdvertising {

    if (_advertising){
        NSLog(@"Already advertising");
        return;
    }

    self.acceptedPeerIDNameMap = [NSMutableDictionary dictionary];

    NSInteger timeStamp = [self shortenedNetworkTimeStamp];
    NSDictionary *discoveryInfo = @{kAdvertisingDiscoveryInfoTimestampKey:[NSString   stringWithFormat:@"%ld",(long)timeStamp]};

    NSLog(@"Starting advertiser");

    self.serviceAdvertiser = [[MCNearbyServiceAdvertiser alloc] initWithPeer:_myPeerID
                                                           discoveryInfo:discoveryInfo
                                                             serviceType:kServiceType];
    _serviceAdvertiser.delegate = self;

    [_serviceAdvertiser startAdvertisingPeer];

    self.advertising = YES;
}

The method shortenedNetworkTimestamp just takes an NSTimeInterval (either using the ntp framework or timeIntervalSinceReferenceDate and removing 1400000000 from it.

Then when the browser discovers a peer, it checks whether the advertiser's timestamp is within the known discovery duration (in my case 60 seconds):

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info {

    DLog(@"Browser found peer ID %@",peerID.displayName);

    //Only one peer should invite the other
    BOOL shouldInvite = [peerID.displayName compare:_myPeerID.displayName]==NSOrderedAscending;

    //Don't re-send invitations
    if (_peerInfoDisplayNameMap[peerID.displayName]){
        DLog(@"Already connected to peerID %@",peerID.displayName);
        shouldInvite = NO;
    }
    else if (_invitedPeerIDNameMap[peerID.displayName]){
            DLog(@"Already invited peerID %@",peerID.displayName);
            shouldInvite = NO;
    }

    //Invite if discovery info is valid
    if (shouldInvite && [self discoveryInfoIsValid:info]) {

        DLog(@"Inviting");

        _invitedPeerIDNameMap[peerID.displayName] = peerID;

        MCSession *session = [self availableSession];
        [_serviceBrowser invitePeer:peerID toSession:session withContext:nil timeout:0];
    }
    else {
        DLog(@"Not inviting");
    }
 }

The discovery info validity check is pretty simple - just make sure the timestamp sent in the info is inside of the discovery time range (in my case kDiscoveryPhaseDuration is 60 seconds):

- (BOOL)discoveryInfoIsValid:(NSDictionary *)info {

    BOOL isValid = YES;

    NSString *infoTimeStamp = info[kAdvertisingDiscoveryInfoTimestampKey];
    NSTimeInterval sentTimeStamp = (infoTimeStamp) ? [infoTimeStamp doubleValue] : -1;
    NSTimeInterval currentTimeStamp = [self shortenedNetworkTimeStamp];

    if (sentTimeStamp==-1 || (currentTimeStamp - sentTimeStamp) > kDiscoveryPhaseDuration){
        DLog(@"Expired discovery info (current=%f, sent=%f)",currentTimeStamp,sentTimeStamp);
        isValid = NO;
    }

    return isValid;
}

Hopefully this helps. There are many other quirks in MPC that I'm handling in my own code but I think the above covers this specific problem.




回答2:


This isn't possible with Multipeer Connectivity. There are no methods Apple puts in place to limit the connection to Bluetooth.

One answer here: Multipeer connectivity over Bluetooth? states "There is no explicit setting for bluetooth or Wifi, It will connect devices in whatever possible way they are available."



来源:https://stackoverflow.com/questions/26289811/disable-wifi-from-multi-peer-connectivity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!