iOS中蓝牙实现方案

iOS中提供了4个框架用于蓝牙连接

  • GameKit.framework (用法简单)

  • 只能用于iOS设备之间的连接,多用于游戏,比如(五子棋),iOS7以后过期

  • MultipeerConnectivity.framework

  • 只能用于iOS设备之间连接

  • ExternalAccessory.framework

  • 可用于第三方蓝牙设备交互,但是蓝牙设备必须经过苹果MFi认证(国内较少)

  • CoreBlueTooth.framework(时下热门)

  • 可用于第三方设备交互,必须支持蓝牙4.0

  • 硬件至少4s,系统至少6.0

  • 蓝牙4.0以低功耗著称,一般也叫BLE(Bluetooth Low Energy)

GameKit框架的实现

#import "ViewController.h"
#import 
@interface ViewController () 
@property (weak, nonatomic) IBOutlet UIImageView *showImage;
/** 会话*/
@property (nonatomic, weak) GKSession *session;
- (IBAction)connectBlueTooth;

- (IBAction)pickerImage;
- (IBAction)sendImage;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}
#pragma mark - 连接蓝牙
- (IBAction)connectBlueTooth {
   //创建连接设备的控制器
    GKPeerPickerController *peerPicker = [[GKPeerPickerController alloc]init];
    peerPicker.delegate = self;
    [peerPicker show];
}
#pragma mark - 选择照片
- (IBAction)pickerImage {
    //判断照片源是否可用
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
        NSLog(@"相簿不可用!");
        return;
    }
    //创建照片pickerVc
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
    imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    imagePicker.delegate = self;
    [self presentViewController:imagePicker animated:YES completion:nil];
}
#pragma mark - 发送照片
- (IBAction)sendImage {
    NSData *data = UIImageJPEGRepresentation(self.showImage.image, 1.0);
    [self.session sendDataToAllPeers:data withDataMode:GKSendDataReliable error:nil];
}
#pragma mark - 代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
    //设置相片
    self.showImage.image = image;
    [picker dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - 会话代理方法
//peerID 节点ID 每一个蓝牙设备都是一个节点ID 都对应一个ID
//session 会话 建立连接之后相当于两个蓝牙建立了一个会话 之后可以通过会话来传递数据
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
    NSLog(@"连接成功");
    //设置句柄
    [session setDataReceiveHandler:self withContext:nil];
    //保存会话
    self.session = session;
    [picker dismiss];
}
#pragma mark - 句柄回调方法
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
    self.showImage.image = [[UIImage alloc]initWithData:data];
}
@end

MultipeerConnectivity实现

#import "ViewController.h"
#import 
#define SERVICE_TYPE @"love"
@interface ViewController () 
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
/**会话 */
@property (nonatomic, strong) MCSession *session;
/**广告 */
@property (nonatomic, strong) MCAdvertiserAssistant *ad;
/**peer */
@property (nonatomic, strong) MCPeerID *peerID;
@end

@implementation ViewController
//注册一个广告自己的设备可以被扫描到
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.session = [[MCSession alloc]initWithPeer:[[MCPeerID alloc]initWithDisplayName:[UIDevice currentDevice].name]];
    self.session.delegate = self;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)connect:(id)sender {
    MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:SERVICE_TYPE session:self.session];
    browser.delegate = self;
    [self presentViewController:browser animated:YES completion:nil];
}

- (IBAction)picker:(id)sender {
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera | UIImagePickerControllerSourceTypePhotoLibrary]) return;
    UIImagePickerController *picker = [[UIImagePickerController alloc]init];
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    picker.delegate = self;
    [self presentViewController:picker animated:YES completion:nil];
}
- (IBAction)send:(id)sender {
    UIImage *image = self.imageView.image;
    if (image) {
        NSData *data = UIImagePNGRepresentation(image);
        [self.session sendData:data toPeers:@[self.peerID] withMode:MCSessionSendDataReliable error:nil];
    }
}
- (IBAction)canSee:(id)sender {
    UISwitch *s = (UISwitch *)sender;
    if (s.isOn) {
        //注册广告 可能一个设备发送了多个广告 所以需要绑定唯一标识
        self.ad = [[MCAdvertiserAssistant alloc]initWithServiceType:SERVICE_TYPE discoveryInfo:nil session:self.session];
        [self.ad start];
    }
}
#pragma mark - picker
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo{
    self.imageView.image = image;
    [self dismissViewControllerAnimated:YES completion:nil];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    [self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - browser
//连接成功
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController{
    [browserViewController dismissViewControllerAnimated:YES completion:nil];
}

//连接失败
- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController{
    [browserViewController dismissViewControllerAnimated:YES completion:nil];
}

//连接哪个设备
- (BOOL)browserViewController:(MCBrowserViewController *)browserViewController
      shouldPresentNearbyPeer:(MCPeerID *)peerID
            withDiscoveryInfo:(nullable NSDictionary *)info{
    self.peerID = peerID;
    return YES;
}
#pragma mark - session
// 远程匹配状态改变
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{
    NSLog(@"%s %d",__func__,__LINE__);
}

//接收到数据
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{
    if (data) {
        self.imageView.image = [UIImage imageWithData:data];
    }
}

// Received a byte stream from remote peer.
- (void)    session:(MCSession *)session
   didReceiveStream:(NSInputStream *)stream
           withName:(NSString *)streamName
           fromPeer:(MCPeerID *)peerID{
    
}

// Start receiving a resource from remote peer.
- (void)                    session:(MCSession *)session
  didStartReceivingResourceWithName:(NSString *)resourceName
                           fromPeer:(MCPeerID *)peerID
                       withProgress:(NSProgress *)progress{
    
}

// Finished receiving a resource from remote peer and saved the content
// in a temporary location - the app is responsible for moving the file
// to a permanent location within its sandbox.
- (void)                    session:(MCSession *)session
 didFinishReceivingResourceWithName:(NSString *)resourceName
                           fromPeer:(MCPeerID *)peerID
                              atURL:(NSURL *)localURL
                          withError:(nullable NSError *)error{
    
}
@end

ble连接广告和扫描服务与特征

#import "ViewController.h"
#import 
/*
 * 1.建立中心管家
   2.扫描外部设备
   3.连接外部设备
   4.扫描外部服务和特征
   5.数据交互
   6.断开连接
 
 */
@interface ViewController () 
/**中心管家 */
@property (nonatomic, strong) CBCentralManager *mgr;
/**外设 */
@property (nonatomic, strong) CBPeripheral *peripheral;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建中心管家
    self.mgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
    self.mgr.delegate = self;
    
}

#pragma mark - mgr
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    //开机状态下才扫描
    if (central.state == CBManagerStatePoweredOn) {
        //扫描外设
        [self.mgr scanForPeripheralsWithServices:nil options:nil];
    }
}

//扫描到外设
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    self.peripheral = peripheral;
    self.peripheral.delegate = self;
    //连接外设
    [self.mgr connectPeripheral:peripheral options:nil];
}

//连接上外设
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"连接到外设");
    [peripheral discoverServices:nil];
}

#pragma mark - peripheral
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    NSLog(@"扫描到服务");
    //扫描特征
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    NSLog(@"扫描到特征");
    //扫描描述
    for (CBCharacteristic *characteristic in service.characteristics) {
        [peripheral discoverDescriptorsForCharacteristic:characteristic];
        [peripheral readValueForCharacteristic:characteristic];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    NSLog(@"扫描到描述");
    for (CBDescriptor *descriptor in characteristic.descriptors) {
        NSLog(@"描述:%@",descriptor.description);
        [peripheral readValueForDescriptor:descriptor];
    }
}
@end

你可能感兴趣的:(iOS中蓝牙实现方案)