藍(lán)牙
1.GameKit
簡介:
- 實現(xiàn)藍(lán)牙設(shè)備之間的通訊
- 只能使用在iOS設(shè)備之間同一個應(yīng)用內(nèi)連接
- 從iOS7開始過期了
- 但是GameKit是最基本的藍(lán)牙通訊框架
- 通過藍(lán)牙可以實現(xiàn)文件的共享(僅限設(shè)備沙盒中的文件)
- 此框架一般用于游戲開發(fā)(比如五子棋對戰(zhàn))
#import "ViewController.h"
#import <GameKit/GameKit.h>
@interface ViewController ()<GKPeerPickerControllerDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate>
/**
* 顯示圖片
*/
@property (weak, nonatomic) IBOutlet UIImageView *showImg;
/*
* 保存當(dāng)前回話
*/
@property (nonatomic, strong) GKSession *session;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - delegate
/*
* 連接藍(lán)牙的方式 附近 在線
*/
- (void)peerPickerController:(GKPeerPickerController *)picker didSelectConnectionType:(GKPeerPickerConnectionType)type {
NSLog(@"%s %d type =%lu picker %@",__func__,__LINE__,(unsigned long)type,picker);
}
// 連接會話的方式 附近 在線
- (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type {
return nil;
}
/* 連接成功
* peerID 連接成功的設(shè)備id
* session 當(dāng)前回話 只需要保存當(dāng)前的會話 即 可 數(shù)據(jù)傳遞
*/
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session {
// 隱藏選擇器
[picker dismiss];
// 接收數(shù)據(jù)的回調(diào) GameKIt 必須實現(xiàn)的
[session setDataReceiveHandler:self withContext:nil];
// 保存會話
self.session = session;
}
// 只要有數(shù)據(jù)回來 那么就會調(diào)用
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
// if (!data) return;
// 轉(zhuǎn)換圖片
UIImage *img = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
self.showImg.image = img;
});
}
/*
* 退出
*/
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
}
#pragma mark - imageDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
self.showImg.image = info[UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - 按鈕的點擊
- (IBAction)connect:(id)sender {
// 創(chuàng)建藍(lán)牙選擇器
GKPeerPickerController *picker = [[GKPeerPickerController alloc]init];
picker.delegate = self;
// 顯示
[picker show];
}
- (IBAction)selectImg:(id)sender {
UIImagePickerController *imgPicker = [[UIImagePickerController alloc]init];
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:imgPicker animated:YES completion:nil];
}
- (IBAction)sendImg:(id)sender {
if (!self.showImg.image) return;
//圖片轉(zhuǎn)化
NSData *data = UIImagePNGRepresentation(self.showImg.image);
// GKSendDataReliable 安全模式
// GKSendDataUnreliable 不安全模式
[self.session sendDataToAllPeers:data withDataMode:GKSendDataUnreliable error:nil];
NSLog(@"session = %@" , self.session);
}
@end
2.mutipeerConnectivity
- iOS 7引入的一個全新框架
- 多點連接
- 替代GameKit框架
- 多用于文件的傳輸
- iOS設(shè)備不聯(lián)網(wǎng)也能跟附近的人聊天
- FireChat
- See You Around
- 以上近場聊天App都是基于mutipeerConnectivity框架
- 搜索和傳輸?shù)姆绞?
- 雙方WIFI和藍(lán)牙都沒有打開:無法實現(xiàn)
- 雙方都開啟藍(lán)牙:通過藍(lán)牙發(fā)現(xiàn)和傳輸
- 雙方都開啟WIFI:通過WIFI Direct發(fā)現(xiàn)和傳輸衷掷,速度接近AirDrop
- 雙方同時開啟了WIFI和藍(lán)牙:模擬AirDrop,通過低功耗藍(lán)牙技術(shù)掃描發(fā)現(xiàn)握手脯宿,然后通過WIFI Direct傳輸
#import "ViewController.h"
#import <MultipeerConnectivity/MultipeerConnectivity.h>
/*
1. 注冊一個廣告 告訴別人 我的設(shè)備是可以被發(fā)現(xiàn)
2. 掃描藍(lán)牙設(shè)備 需要實現(xiàn)代理方法
3. 使用一個MCSession對象存儲當(dāng)前會話 需要實現(xiàn)代理方法
4. 使用MCSession 對象 發(fā)送和接收數(shù)據(jù)
*/
#define SERVICE_TYPE @"xmg"
@interface ViewController ()<MCBrowserViewControllerDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate,MCSessionDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *showImg;
// 保存會話
@property (nonatomic, strong)MCSession *m_session;
/** 發(fā)送廣告 */
@property (nonatomic, strong) MCAdvertiserAssistant *assistant;
/** 當(dāng)前連接到的設(shè)備 */
@property (nonatomic, strong) MCPeerID *peerId;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化 會話
// 獲取設(shè)備的名字
NSString *displayName = [UIDevice currentDevice].name;
// 設(shè)備的id
MCPeerID *perrID = [[MCPeerID alloc]initWithDisplayName:displayName];
self.m_session = [[MCSession alloc]initWithPeer:perrID];
self.m_session.delegate = self;
}
// click events
- (IBAction)connect:(id)sender {
MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:SERVICE_TYPE session:self.m_session];
browser.delegate = self;
[self presentViewController:browser animated:YES completion:nil];
}
- (IBAction)selecte:(id)sender {
UIImagePickerController *imgPicker = [[UIImagePickerController alloc]init];
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:imgPicker animated:YES completion:nil];
}
- (IBAction)sendImage:(id)sender {
if (!self.showImg.image) return;
// 發(fā)送數(shù)據(jù)
[self.m_session sendData:UIImagePNGRepresentation(self.showImg.image) toPeers:@[self.peerId] withMode:MCSessionSendDataUnreliable error:nil];
NSLog(@"===%@" ,self.m_session);
}
// 設(shè)置可被發(fā)現(xiàn)
- (IBAction)found:(id)sender {
UISwitch *s = (UISwitch *)sender;
if (s.isOn) {
// 注冊廣告 可能一個app 發(fā)送了多個廣告, 所以需要給光綁定唯一標(biāo)示
self.assistant = [[MCAdvertiserAssistant alloc]initWithServiceType:SERVICE_TYPE discoveryInfo:nil session:self.m_session];
[self.assistant start];
}
}
#pragma mark - 會話的代理方法
// 接收到的數(shù)據(jù)
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
dispatch_async(dispatch_get_main_queue(), ^{
self.showImg.image = [UIImage imageWithData:data];
});
}
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
}
#pragma mark - 掃描設(shè)備的代理
// 連接成功
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
{
NSLog(@"%s %d",__func__,__LINE__);
[browserViewController dismissViewControllerAnimated:YES completion:nil];
}
// 退出連接
- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
{
}
// 連接哪個設(shè)備
- (BOOL)browserViewController:(MCBrowserViewController *)browserViewController
shouldPresentNearbyPeer:(MCPeerID *)peerID
withDiscoveryInfo:(nullable NSDictionary<NSString *, NSString *> *)info
{
NSLog(@"%s %d",__func__,__LINE__);
self.peerId = peerID;
return YES;
}
#pragma mark - imageDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
self.showImg.image = info[UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}
@end
3.CoreBlueTooth
- 可用于第三方藍(lán)牙設(shè)備交互,設(shè)備必須支持藍(lán)牙4.0
- iPhone的設(shè)備必須是4S或者更新
- iPad設(shè)備必須是iPad mini或者更新
- iOS的系統(tǒng)必須是iOS 6或者更新
- 藍(lán)牙4.0以
低功耗
著稱,所以一般被稱為BLE(bluetooth low energy) - 使用模擬器調(diào)試
- Xcode 4.6
- iOS 6.1
- 應(yīng)用場景
- 運動手環(huán)
- 智能家居
- 拉卡拉藍(lán)牙刷卡器
核心概念
- CBCentralManager:中心設(shè)備(用來連接到外部設(shè)備的管家)
- CBPeripheralManager:外部設(shè)備(第三方的藍(lán)牙4.0設(shè)備)
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
@interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)NSMutableArray *peripherals;
@property(nonatomic,strong)CBCentralManager *cmgr;
@end
@implementation ViewController
- (NSMutableArray *)peripherals
{
if (!_peripherals) {
_peripherals = [NSMutableArray array];
}
return _peripherals;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 創(chuàng)建中心管家,并且設(shè)置代理
self.cmgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
// 2. 掃描外部設(shè)備
/**
* scanForPeripheralsWithServices :如果傳入指定的數(shù)組,那么就只會掃描數(shù)組中對應(yīng)ID的設(shè)備
* 如果傳入nil,那么就是掃描所有可以發(fā)現(xiàn)的設(shè)備
* 掃描完外部設(shè)備就會通知CBCentralManager的代理
*/
if ([self.cmgr state]== CBCentralManagerStatePoweredOn) {
[self.cmgr scanForPeripheralsWithServices:nil options:0];
}
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSLog(@"%s %d",__func__,__LINE__);
}
#pragma mark - CBCentralManagerDelegate
/**
* 發(fā)現(xiàn)外部設(shè)備莽囤,每發(fā)現(xiàn)一個就會調(diào)用這個方法
* 所以可以使用一個數(shù)組來存儲每次掃描完成的數(shù)組
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"%s %d",__func__,__LINE__);
// 有可能會導(dǎo)致重復(fù)添加掃描到的外設(shè)
// 所以需要先判斷數(shù)組中是否包含這個外設(shè)
if(![self.peripherals containsObject:peripheral]){
[self.peripherals addObject:peripheral];
}
}
/**
* 連接外設(shè)成功調(diào)用
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"%s %d",__func__,__LINE__);
// 查找外設(shè)服務(wù)
[peripheral discoverServices:nil];
}
/**
* 模擬開始連接方法
*/
- (void)start
{
NSLog(@"%s %d",__func__,__LINE__);
// 3. 連接外設(shè)
for (CBPeripheral *ppl in self.peripherals) {
// 掃描外設(shè)的服務(wù)
// 這個操作應(yīng)該交給外設(shè)的代理方法來做
// 設(shè)置代理
ppl.delegate = self;
[self.cmgr connectPeripheral:ppl options:nil];
}
}
#pragma mark - CBPeripheralDelegate
/**
* 發(fā)現(xiàn)服務(wù)就會調(diào)用代理方法
*
* @param peripheral 外設(shè)
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(@"%s %d",__func__,__LINE__);
// 掃描到設(shè)備的所有服務(wù)
NSArray *services = peripheral.services;
// 根據(jù)服務(wù)再次掃描每個服務(wù)對應(yīng)的特征
for (CBService *ses in services) {
[peripheral discoverCharacteristics:nil forService:ses];
}
}
/**
* 發(fā)現(xiàn)服務(wù)對應(yīng)的特征
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
NSLog(@"%s %d",__func__,__LINE__);
// 服務(wù)對應(yīng)的特征
NSArray *ctcs = service.characteristics;
// 遍歷所有的特征
for (CBCharacteristic *character in ctcs) {
// 根據(jù)特征的唯一標(biāo)示過濾
if ([character.UUID.UUIDString isEqualToString:@"XMG"]) {
NSLog(@"可以吃飯了");
}
}
}
/**
* 斷開連接
*/
- (void)stop
{
NSLog(@"%s %d",__func__,__LINE__);
// 斷開所有連接上的外設(shè)
for (CBPeripheral *per in self.peripherals) {
[self.cmgr cancelPeripheralConnection:per];
}
}
@end
4.運動手環(huán)
#import "ViewController.h"
#import "XMGBandingController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *userField;
@property (weak, nonatomic) IBOutlet UITextField *pswFeild;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)loginClick:(id)sender {
self.userField.text = @"361283017@qq.com";
self.pswFeild.text = @"361283017xj";
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:self.userField.text forKey:@"account"];
// 78:A5:04:38:53:75
//#ifdef DEBUG
// [params setObject:@"lepao321lepao" forKey:@"password"];//測試時可以不用密碼登陸
//#else
[params setObject:[self.pswFeild.text md5] forKey:@"password"];
//#endif
[params setObject:[UIDevice BIData] forKey:@"deviceInfo"];
[params setObject:@"AppStore" forKey:@"creative"];
[params setObject:[UIDevice IPv4] forKey:@"ip"];
// [TCLoadingView showWithLoadingText:@"正在加載中"];
[[HttpManager defaultManager] getRequestToUrl:url_login params:params complete:^(BOOL successed, NSDictionary *result) {
if (successed && [[result objectForKey:@"ret"] intValue]==1) {
NSLog(@"----result = %@",result);
XMGBandingController *bangding = [[XMGBandingController alloc]init];
[self.navigationController pushViewController:bangding animated:YES];
}else{
// [KeyWindow showAlertMessage:result?result[@"msg"]:@"服務(wù)器忙,請稍后再試" callback:nil];
}
// [TCLoadingView removeLoadingView];
}];
}
@end
#import "XMGBandingController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#define BLE_SERVICE_UUID @"FEE7"
#define BLE_WIRTE_UUID @"FEC7"
#define BLE_READ_UUID @"FEC8"
@interface XMGBandingController ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (nonatomic,strong)CBCentralManager *cmgr;
@property (nonatomic,strong)CBPeripheral *peripheral;
@end
@implementation XMGBandingController
- (void)viewDidLoad
{
[super viewDidLoad];
// @[@"78:A5:04:38:53:75"]
self.view.backgroundColor = [UIColor whiteColor];
// 建立中心管家
self.cmgr = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
// 掃描外接設(shè)備
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if ([central state] == CBCentralManagerStatePoweredOn) {
[self.cmgr scanForPeripheralsWithServices:nil options:nil];
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"peripheral = %@",peripheral);
self.peripheral = peripheral;
self.peripheral.delegate = self;
[self.cmgr connectPeripheral:self.peripheral options:nil];
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"%s %d",__func__,__LINE__);
[self.peripheral discoverServices:nil];
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(@"=====%@",peripheral.services);
for (CBService *service in peripheral.services) {
if([service.UUID.UUIDString isEqualToString:@"FEE7"]){
[service.peripheral discoverCharacteristics:nil forService:service];
}
}
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
NSLog(@"------%@",service.characteristics);
for (CBCharacteristic *chtcs in service.characteristics) {
[self.peripheral discoverDescriptorsForCharacteristic:chtcs];
[self.peripheral readValueForCharacteristic:chtcs];
}
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSLog(@"%s %d",__func__,__LINE__);
NSLog(@"------%@",characteristic);
for (CBDescriptor *dpr in characteristic.descriptors) {
[self.peripheral readValueForDescriptor:dpr];
}
}
@end