蓝牙连接立即断开多点框架

Posted

技术标签:

【中文标题】蓝牙连接立即断开多点框架【英文标题】:bluetooth connection is immediately disconnecting multipeer framework 【发布时间】:2014-06-04 05:17:07 【问题描述】:

我正在尝试使用多点连接框架建立一对一的点对点连接。当我向附近的对等方发送邀请时,该设备已连接(有时需要很长时间才能连接),并且发送请求的对等方总是需要很长时间才能将其状态更改为已连接,一旦立即连接,它就会断开连接从会话。我尝试调试问题但没有发现任何问题,不知道发生了什么问题,如果我遗漏任何内容或代码中有任何错误,请告诉我。

下面给出的是相同的代码sn-p。

MPCHandler.m

#define DidChangeStateNotification @"E_DidChangeStateNotification"
#define DidReceiveDataNotification @"E_DidReceiveDataNotification"
#define DidInviteNotification @"E_DidInvitedNotification"
#define DidReceivedInvetationNotification @"E_DidReceivedInvetationNotification"

static NSString * const EServiceType = @"E-service";

@interface MPCHandler ()
@property AppDelegate *appDelegate;
@end

@implementation MPCHandler

- (void)setupPeerWithDisplayName:(NSString *)displayName 

    self.appDelegate = [[UIApplication sharedApplication] delegate];
    self.peerID = [[MCPeerID alloc] initWithDisplayName:displayName];

    self.connectedPeers = [NSMutableArray array];
    self.foundPeers = [NSMutableArray array];
    self.invitedPeers = [NSMutableArray array];


- (void)setupSession 

    self.session = [[MCSession alloc] initWithPeer:self.peerID securityIdentity:nil    encryptionPreference:MCEncryptionNone];
    self.session.delegate = self;


- (void)setupBrowser 

    self.browser = [[MCNearbyServiceBrowser alloc] initWithPeer:self.peerID serviceType:EServiceType];
    self.browser.delegate = self;



- (void)advertiseSelf:(BOOL)advertise 

    if (advertise) 
        self.advertiser = [[MCNearbyServiceAdvertiser alloc] initWithPeer:self.peerID discoveryInfo:nil serviceType:EServiceType];
        self.advertiser.delegate = self;
        [self.advertiser startAdvertisingPeer];

     else 
        [self.advertiser stopAdvertisingPeer];
        self.advertiser = nil;
    


#pragma MCSessionDelegate methods

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state 
    NSDictionary *userInfo = @ @"peerID": peerID,
                            @"state" : @(state) ;

    dispatch_async(dispatch_get_main_queue(), ^
        [[NSNotificationCenter defaultCenter] postNotificationName:DidChangeStateNotification
                                                        object:nil
                                                      userInfo:userInfo];
    );


- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID 
    NSDictionary *userInfo = @ @"data": data,
                            @"peerID": peerID ;

    dispatch_async(dispatch_get_main_queue(), ^
        [[NSNotificationCenter defaultCenter] postNotificationName:DidReceiveDataNotification
                                                        object:nil
                                                      userInfo:userInfo];
    );


- (void)session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL))certificateHandler
certificateHandler(YES);

#pragma MCNearbyServiceAdvertiserDelegate 方法

    // Incoming invitation request.  Call the invitationHandler block with YES and a valid session  to connect the inviting peer to the session.
 - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler


   NSDictionary *info =[NSDictionary dictionaryWithObject:peerID.displayName forKey:@"displayName"];
   NSLog(@"%@ Received Invetation from : %@",self.peerID.displayName,peerID.displayName);

   invitationHandler(YES,self.session);

   [self.connectedPeers addObject:peerID];
   self.invited = NO;

   dispatch_async(dispatch_get_main_queue(), ^

       [[NSNotificationCenter defaultCenter] postNotificationName:DidReceivedInvetationNotification
                                                        object:nil
                                                      userInfo:info];
   );

#pragma MCNearbyServiceBrowserDelegate 方法

// Found a nearby advertising peer
 - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:  (NSDictionary *)info

  //    NSLog(@"Peer : %@ found.",peerID.displayName);

     //    if (![self.peerID isEqual:peerID]) 

     NSLog(@"%@ Found Peer : %@",self.peerID.displayName,peerID.displayName);

    [self.foundPeers addObject:peerID];

     if (![self.connectedPeers containsObject:peerID])
     
         if ([self.invitedPeers count] == 0 && [self.session.connectedPeers count]==0)
        

            NSLog(@"%@ Invited Peer : %@",self.peerID.displayName,peerID.displayName);

            [self.invitedPeers addObject:peerID];

            [browser invitePeer:peerID
                       toSession:self.session
                    withContext:[@"Empath" dataUsingEncoding:NSUTF8StringEncoding]
                    timeout:0];

        //            [browser stopBrowsingForPeers];

                   self.invited = YES;

                NSDictionary *userInfo = @ @"peerID": peerID ;

               dispatch_async(dispatch_get_main_queue(), ^

                    [[NSNotificationCenter defaultCenter] postNotificationName:DidInviteNotification
                                                                object:nil
                                                              userInfo:userInfo];
                );
          
       

        //    
  

  // A nearby peer has stopped advertising
  - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
      [self.foundPeers removeObject:peerID];
     [self.invitedPeers removeAllObjects];
    [browser startBrowsingForPeers];
  
 - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error

      NSLog( @"Unable to start browsing for peers. Error: %@", error );
 

   ViewController.m

#define DidChangeStateNotification @"E_DidChangeStateNotification"
#define DidReceiveDataNotification @"E_DidReceiveDataNotification"
#define DidInviteNotification @"E_DidInvitedNotification"
#define DidReceivedInvetationNotification @"E_DidReceivedInvetationNotification"

@interface ViewController ()
@property (nonatomic, strong) AppDelegate *appDelegate;
@end

@implementation ViewController

@synthesize txtMessage;
@synthesize tvHistory;
@synthesize btnSend;
@synthesize lblName;

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
//    self.appDelegate.connectedPeers = [NSMutableArray array];
//    self.appDelegate.foundPeers = [NSMutableArray array];

    [self AddObservers];

    [self setUserInteraction:NO];
    [self.lblName setText:@""];
    [self.btnSend setUserInteractionEnabled:NO];
    [self performSelector:@selector(advertisePeer) withObject:nil afterDelay:0.0];


-(void) AddObservers

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleReceivedDataWithNotification:)
                                                 name:DidReceiveDataNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(peerChangedStateWithNotification:)
                                                 name:DidChangeStateNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(receivedInvetationWithNotification:)
                                                 name:DidReceivedInvetationNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(peerInvitedWithNotification:)
                                                 name:DidInviteNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(sessionDidTimeout:)     name:kSessionDidTimeoutNotification object:nil];

-(void) advertisePeer

    [self setUserInteraction:NO];
    [self.lblName setText:@""];
    [self.appDelegate.mpcHandler setupPeerWithDisplayName:[UIDevice currentDevice].name];
    [self.appDelegate.mpcHandler setupSession];
    [self.appDelegate.mpcHandler advertiseSelf:YES];
    [self.btnSend setUserInteractionEnabled:YES];


- (IBAction)searchAndConnectPeer:(id)sender

        [self.lblName setText:@"Searching..."];
        if (self.appDelegate.mpcHandler.session != nil) 
            [[self.appDelegate mpcHandler] setupBrowser];

            [[[self.appDelegate mpcHandler] browser] startBrowsingForPeers];

        


- (IBAction)sendMessage:(id)sender

    NSString *messageToSend = [txtMessage text];
    NSUInteger len = 0;
    if ([messageToSend length]) 

        NSData *messageAsData = [messageToSend dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error;

        [self.appDelegate.mpcHandler.session sendData:messageAsData
                                          toPeers:self.appDelegate.mpcHandler.session.connectedPeers
                                         withMode:MCSessionSendDataReliable
                                            error:&error];

        // If any error occurs, just log it.
        // Otherwise set the following couple of flags to YES, indicating that the current player is the creator
        // of the game and a game is in progress.
         len = [[tvHistory text] length];
         if (error != nil) 
            NSLog(@"%@", [error localizedDescription]);
           [self.tvHistory setText:[NSString stringWithFormat:@"%@",[error localizedDescription]]];
         else

            NSString *history = [NSString stringWithFormat:@"Me : %@\n\n",messageToSend];
            [self.tvHistory setText:[self.tvHistory.text stringByAppendingString:history]];
        
    

     [self.txtMessage setText:@""];
    [self.tvHistory scrollRangeToVisible:NSMakeRange([self.tvHistory.text length], len)];

- (void)peerInvitedWithNotification:(NSNotification *)notification
    [self setUserInteraction:NO];
     MCPeerID *peerID = [[notification userInfo] objectForKey:@"peerID"];
    [self.lblName setText:[NSString stringWithFormat:@"Connecting to %@...",peerID.displayName]];

- (void)receivedInvetationWithNotification:(NSNotification *)notification
    [self setUserInteraction:YES];
    NSString *name = [[notification userInfo] objectForKey:@"displayName"];
    [self.lblName setText:[NSString stringWithFormat:@"Connected : %@",name]];

- (void)peerChangedStateWithNotification:(NSNotification *)notification 
    // Get the state of the peer.

    int state = [[[notification userInfo] objectForKey:@"state"] intValue];
    MCPeerID *peerID = [[notification userInfo] objectForKey:@"peerID"];

    // We care only for the Connected and the Not Connected states.
    // The Connecting state will be simply ignored.
    if (state == MCSessionStateConnected) 

        // We'll just display all the connected peers (players) to the text view.
        NSString *allPlayers = @"Connected : ";

        allPlayers = [allPlayers stringByAppendingString:[NSString tringWithFormat:@"%@",peerID.displayName]];
        [self.lblName setText:allPlayers];
        [self setUserInteraction:YES];
        NSLog(@"%@...",allPlayers);
//        // Fire up the timer upon first event
//        if(!_idleTimer) 
//            [self resetIdleTimer];
//        

    else if (state == MCSessionStateConnecting)

        [self setUserInteraction:NO];
        [self.lblName setText:[NSString stringWithFormat:@"Connecting to %@...",peerID.displayName]];
        NSLog(@"Connecting %@...",peerID.displayName);

    else if (state == MCSessionStateNotConnected)

        NSLog(@"Disconnected %@...",peerID.displayName);
//        [self sessionDidTimeout:nil];
    

-(void) setUserInteraction:(BOOL)enabled
    [self.btnSend setUserInteractionEnabled:enabled];
    [self.txtMessage setUserInteractionEnabled:enabled];

- (void)handleReceivedDataWithNotification:(NSNotification *)notification 
    // Get the user info dictionary that was received along with the notification.
    NSDictionary *userInfoDict = [notification userInfo];

    // Convert the received data into a NSString object.
    NSData *receivedData = [userInfoDict objectForKey:@"data"];
    NSString *message = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];

    // Keep the sender's peerID and get its display name.
    MCPeerID *senderPeerID = [userInfoDict objectForKey:@"peerID"];
    NSString *senderDisplayName = senderPeerID.displayName;

    // Add this guess to the history text view.
    NSUInteger len = [[tvHistory text] length];
    NSString *history = [NSString stringWithFormat:@"%@ : %@\n\n", senderDisplayName, message];
    [self.tvHistory setText:[self.tvHistory.text stringByAppendingString:history]];
    [self.tvHistory scrollRangeToVisible:NSMakeRange([self.tvHistory.text length], len)];


-(BOOL)textFieldShouldReturn:(UITextField *)textField
    [textField resignFirstResponder];
    return YES;


- (void)resetIdleTimer

    if (_idleTimer) 
        [_idleTimer invalidate];

    

    // Schedule a timer to fire in kApplicationTimeoutInMinutes * 60
        int timeout = kSessionTimeoutInSeconds;
     _idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout
                                               target:self
                                        selector:@selector(idleTimerExceeded)
                                             userInfo:nil
                                              repeats:NO];


- (void)idleTimerExceeded 
    /* Post a notification so anyone who subscribes to it can be notified when
     * the application times out */
    [[NSNotificationCenter defaultCenter]
     postNotificationName:kSessionDidTimeoutNotification object:nil];

- (void) sessionDidTimeout:(NSNotification *) notif 

//    [self setUserInteraction:NO];
//    
//    [self.lblName setText:@"Session expired..."];
//    
//    NSLog(@"============================Session Expired...=====================");
//    
//    [[[self.appDelegate mpcHandler] session]  disconnect];
//    
//    if ([[[self appDelegate]mpcHandler] invited]) 
//        [self performSelector:@selector(advertisePeer) withObject:nil afterDelay:0.0];
//        [self performSelector:@selector(searchAndConnectPeer:) withObject:nil afterDelay:1.0];
//    

【问题讨论】:

任何人都可以在上面指导我 您同时浏览和投放广告。看看这个 SO 问题:***.com/questions/19469984/… 【参考方案1】:

检查 BTM 断开 以在日志中提供服务消息。他们已确认 Apple 蓝牙存在问题。尝试不使用蓝牙,即点对点 wifi 或基础设施网络

【讨论】:

以上是关于蓝牙连接立即断开多点框架的主要内容,如果未能解决你的问题,请参考以下文章

多点连接随机断开

多点连接 - 以编程方式断开对等点

切换 VC 后多点连接会话断开

多人框架 iOS 9.2 中的断开连接问题

蓝牙 LE 在暂停时断开连接

Android 应用程序会自动断开蓝牙连接