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