版权声明:本文为博主原创文章,未经博主允许不得转载。
每日更新关注:http://weibo.com/hanjunqiang 新浪微博
整体布局如下:
程序结构如右图:
每日更新关注:http://weibo.com/hanjunqiang 新浪微博
==========================================================================
指定根视图:
[objc] view plain copy
- RootViewController * rootVC = [[RootViewController alloc] init];
- UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:rootVC];
- self.window.rootViewController= nav;
根视图:
[objc] view plain copy
- #import "RootViewController.h"
- #import "BlueSessionManager.h"
- #import "ChatCell.h"
- #import "ChatItem.h"
- #import <AssetsLibrary/AssetsLibrary.h>
- #import <AVFoundation/AVFoundation.h>
- #define kRecordAudioFile @"myRecord.caf"
- // 判断大小
- #define HEIGHT [UIScreen mainScreen].bounds.size.height
- #define WIDTH [UIScreen mainScreen].bounds.size.width
- #define ChatHeight 45.0
- @interface RootViewController ()<NSStreamDelegate,UITableViewDataSource,UITableViewDelegate,UITextViewDelegate,UIActionSheetDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate,AVAudioRecorderDelegate,AVAudioPlayerDelegate>
- {
- float _sendBackViewHeight;
- float _sendTextViewHeight;
- UIImagePickerController * _picker;
- UIView * _backRemindRecordView;
- }
- // DataAndBlue
- @property(strong, nonatomic) BlueSessionManager *sessionManager;
- @property(strong, nonatomic) NSMutableArray *datasource;
- @property(strong, nonatomic) NSMutableArray * myDataArray;
- @property(strong, nonatomic) NSMutableData *streamData;
- @property(strong, nonatomic) NSOutputStream *outputStream;
- @property(strong, nonatomic) NSInputStream *inputStream;
- // UI
- @property(strong, nonatomic) UITableView * tableView;
- @property(strong, nonatomic) UIView * sendBackView;
- @property(strong, nonatomic) UITextView * sendTextView;
- @property(strong, nonatomic) UIButton * sendButton;
- // 语音播放
- @property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音频录音机
- //音频播放器,用于播放录音文件
- @property (nonatomic,strong) AVAudioPlayer *audioPlayer;
- @property (nonatomic,strong) NSTimer *timer;//录音声波监控(注意这里暂时不对播放进行监控)
- @property (strong, nonatomic) UIProgressView *audioPower;//音频波动
- @end
- @implementation RootViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- [self makeBlueData];
- [self readyUI];
- [self buildVideoForWe];
- // Do any additional setup after loading the view
- }
- #pragma mark 基本制作
- - (void)readyUI
- {
- self.title = @"蓝牙设置";
- self.view.backgroundColor = [UIColor whiteColor];
- self.automaticallyAdjustsScrollViewInsets = NO;
- NSArray * buttonTitleArray = @[@"寻找设备",@"打开天线"];
- self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitleArray[0] style:UIBarButtonItemStyleDone target:self action:@selector(lookOtherDevice)];
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitleArray[1] style:UIBarButtonItemStyleDone target:self action:@selector(showSelfAdvertiser)];
- [self makeUIView];
- }
- - (void)lookOtherDevice
- {
- [self.sessionManager browseWithControllerInViewController:self connected:^{
- NSLog(@"connected");
- } canceled:^{
- NSLog(@"cancelled");
- }];
- }
- - (void)showSelfAdvertiser
- {
- [self.sessionManager advertiseForBrowserViewController];
- }
- #pragma mark 制作页面UI
- - (void)makeUIView
- {
- // NSLog(@"width === %f,height===== %f",WIDTH,HEIGHT);
- self.myDataArray = [NSMutableArray arrayWithCapacity:0];
- self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10)];
- self.tableView.delegate = self;
- self.tableView.dataSource = self;
- self.tableView.separatorStyle = UITableViewCellSelectionStyleNone;
- [self.view addSubview:self.tableView];
- //-------------------------------------------------------------------------//
- self.sendBackView = [[UIView alloc] initWithFrame:CGRectMake(0, HEIGHT - ChatHeight, WIDTH, ChatHeight)];
- self.sendBackView.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
- [self.view addSubview:self.sendBackView];
- // float heightView = self.sendBackView.frame.size.height;
- self.sendTextView = [[UITextView alloc] initWithFrame:CGRectMake(10, 5, WIDTH - 10 - 90, 35)];
- // self.sendTextView.backgroundColor = [UIColor lightGrayColor];
- self.sendTextView.returnKeyType = UIReturnKeySend;
- self.sendTextView.font = [UIFont systemFontOfSize:17];
- self.sendTextView.editable = YES;
- self.sendTextView.delegate = self;
- [self.sendBackView addSubview:self.sendTextView];
- UIButton * addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
- addButton.frame = CGRectMake(WIDTH - 85, 2, 37, 37);
- [addButton addTarget:self action:@selector(addNextImage) forControlEvents:UIControlEventTouchUpInside];
- [self.sendBackView addSubview:addButton];
- self.sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
- self.sendButton.frame = CGRectMake(WIDTH - 45, 5, 40, 30);
- [self.sendButton setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];
- [self.sendButton addTarget:self action:@selector(videoRecord) forControlEvents:UIControlEventTouchUpInside];
- [self.sendBackView addSubview:self.sendButton];
- // 增加通知
- [self addTheNoticeForKeyDownUp];
- }
- #pragma mark 图片的传输---------///////
- - (void)addNextImage
- {
- UIActionSheet *chooseImageSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"照相机",@"相册", nil nil];
- [chooseImageSheet showInView:self.view];
- }
- #pragma mark UIActionSheetDelegate Method
- -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
- {
- _picker = [[UIImagePickerController alloc] init];
- _picker.delegate = self;
- switch (buttonIndex) {
- case 0://Take picture
- if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
- {
- _picker.sourceType = UIImagePickerControllerSourceTypeCamera;
- }
- [self presentViewController:_picker animated:NO completion:nil];
- break;
- case 1:
- //From album
- _picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
- [self presentViewController:_picker animated:NO completion:^{
- // 改变状态栏的颜色 为正常 这是这个独有的地方需要处理的
- [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
- }];
- break;
- default:
- break;
- }
- }
- // 相册
- -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
- {
- NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
- //当选择的类型是图片
- if ([type isEqualToString:@"public.image"])
- {
- //先把图片转成NSData
- UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
- NSData *data;
- if (UIImagePNGRepresentation(image) == nil)
- {
- data = UIImageJPEGRepresentation(image, 1.0);
- }
- else
- {
- data = UIImagePNGRepresentation(image);
- }
- //图片保存的路径
- //这里将图片放在沙盒的documents文件夹中
- NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
- //文件管理器
- NSFileManager *fileManager = [NSFileManager defaultManager];
- //把刚刚图片转换的data对象拷贝至沙盒中 并保存为image.png
- [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil];
- [fileManager createFileAtPath:[DocumentsPath stringByAppendingString:@"/image.png"] contents:data attributes:nil];
- //得到选择后沙盒中图片的完整路径
- NSString * filePath = [[NSString alloc]initWithFormat:@"%@%@",DocumentsPath, @"/image.png"];
- [_picker dismissViewControllerAnimated:NO completion:^{
- // 改变状态栏的颜色 改变为白色
- [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
- // 这边是真正的发送
- if(!self.sessionManager.isConnected)
- {
- UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"蓝牙已经断开了,请重新连接!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];
- [alertView show];
- return;
- }
- ChatItem * chatItem = [[ChatItem alloc] init];
- chatItem.isSelf = YES;
- chatItem.states = picStates;
- chatItem.picImage = image;
- [self.datasource addObject:chatItem];
- [self insertTheTableToButtom];
- [self sendAsResource:filePath];
- }];
- }
- }
- - (void)sendAsResource:(NSString *)path
- {
- NSLog(@"dispaly ====%@",self.sessionManager.firstPeer.displayName);
- NSString * name = [NSString stringWithFormat:@"%@ForPic",[[UIDevice currentDevice] name]];
- NSURL * url = [NSURL fileURLWithPath:path];
- NSProgress *progress = [self.sessionManager sendResourceWithName:name atURL:url toPeer:self.sessionManager.firstPeer complete:^(NSError *error) {
- if(!error) {
- NSLog(@"finished sending resource");
- }
- else {
- NSLog(@"%@", error);
- }
- }];
- NSLog(@"%@", @(progress.fractionCompleted));
- }
- #pragma mark 普通数据的传输
- - (void)sendWeNeedNews
- {
- if(!self.sessionManager.isConnected)
- {
- UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"蓝牙已经断开了,请重新连接!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];
- [alertView show];
- return;
- }
- if([self.sendTextView.text isEqualToString:@""])
- {
- return;
- }
- ChatItem * chatItem = [[ChatItem alloc] init];
- chatItem.isSelf = YES;
- chatItem.states = textStates;
- chatItem.content = self.sendTextView.text;
- [self.datasource addObject:chatItem];
- // 加到数组里面
- // 添加行 indexPath描述位置的具体信息
- [self insertTheTableToButtom];
- NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.sendTextView.text];
- NSError *error = [self.sessionManager sendDataToAllPeers:data];
- if(!error) {
- //there was no error.
- }
- else {
- NSLog(@"%@", error);
- }
- [self returnTheNewBack];
- }
- - (void)returnTheNewBack
- {
- // 归零
- self.sendTextView.text = @"";
- [self.sendTextView resignFirstResponder];
- self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10 );
- self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight , WIDTH, ChatHeight);
- }
- // 这是一种很好的键盘下移方式
- -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
- {
- if ([text isEqualToString:@"\n"]) {
- [self sendWeNeedNews];
- return NO;
- }
- return YES;
- }
- - (void)textViewDidChange:(UITextView *)textView
- {
- // 随机改变其高度
- float textHeight = [self heightForString:textView.text fontSize:16 andWidth:textView.frame.size.width];
- _sendTextViewHeight = textHeight;
- // NSLog(@"teztheight ===== %f",textHeight);
- self.sendTextView.frame = CGRectMake(10, 5, WIDTH - 10 - 90, _sendTextViewHeight);
- self.sendBackView.frame = CGRectMake(0, HEIGHT - _sendBackViewHeight - _sendTextViewHeight - 10, WIDTH, _sendTextViewHeight + 10);
- }
- - (float) heightForString:(NSString *)value fontSize:(float)fontSize andWidth:(float)width
- {
- UITextView *detailTextView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, width, 0)];
- detailTextView.font = [UIFont systemFontOfSize:fontSize];
- detailTextView.text = value;
- CGSize deSize = [detailTextView sizeThatFits:CGSizeMake(width,CGFLOAT_MAX)];
- return deSize.height;
- }
- #pragma mark 以下是为了配合 键盘上移的变化
- - (void)addTheNoticeForKeyDownUp
- {
- [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyBoardDidShow:) name:UIKeyboardDidShowNotification object:nil];
- [ [NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
- }
- - (void)dealloc
- {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- -(void)handleKeyBoardDidShow:(NSNotification *)paramNotification
- {
- CGSize size = [[paramNotification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
- _sendBackViewHeight = size.height;
- [UIView animateWithDuration:0.000001 animations:^{
- self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - size.height);
- self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight - size.height, WIDTH, ChatHeight);
- }];
- }
- -(void)handleKeyboardWillHide:(NSNotification *)paramNotification
- {
- [UIView animateWithDuration:0.1 animations:^{
- if(_sendTextViewHeight > 0)
- {
- self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - _sendTextViewHeight + 10 );
- self.sendBackView.frame = CGRectMake(0, HEIGHT - _sendTextViewHeight - 10, WIDTH, _sendTextViewHeight + 10);
- }
- else
- {
- self.tableView.frame = CGRectMake(0, 64, WIDTH, HEIGHT - 64 - ChatHeight - 10 );
- self.sendBackView.frame = CGRectMake(0, HEIGHT - ChatHeight , WIDTH, ChatHeight);
- }
- }];
- }
- /*--------------------------------------------------------------------------------------------*/
- - (void)insertTheTableToButtom
- {
- // 哪一组 哪一段
- NSIndexPath * indexPath = [NSIndexPath indexPathForRow:self.datasource.count- 1 inSection:0];
- // 添加新的一行
- [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
- // 滑动到底部 第二个参数是滑动到底部
- [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
- }
- #pragma mark tableView 代理
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- return 1;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- return self.datasource.count;
- }
- -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- ChatItem * chatItem = [self.datasource objectAtIndex:indexPath.row];
- if(chatItem.states == picStates)
- {
- NSLog(@"widht====%f,height======%f",chatItem.picImage.size.width,chatItem.picImage.size.height);
- return 50;
- }
- else if(chatItem.states == textStates)
- {
- CGSize size = [chatItem.content boundingRectWithSize:CGSizeMake(250, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:14]} context:nil].size;
- return size.height + 20 + 10; // 与view的距离 + 与Cell的距离
- }
- else
- {
- return 50;
- }
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- static NSString * iden = @"iden";
- ChatCell * cell = [tableView dequeueReusableCellWithIdentifier:iden];
- if(cell == nil)
- {
- cell = [[ChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:iden];
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- // 让后面选中的没有阴影效果
- }
- // 模型
- ChatItem * chatItem = [self.datasource objectAtIndex:indexPath.row];
- CGSize size = [chatItem.content boundingRectWithSize:CGSizeMake(250, 1000) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:14]} context:nil].size;
- //如果自己发的
- if(chatItem.isSelf)
- {
- cell.leftHeadImage.hidden = YES;
- cell.rightHeadImage.hidden = NO;
- if(chatItem.states == picStates)
- {
- cell.lefeView.hidden = YES;
- cell.rightView.hidden = YES;
- cell.rightPicImage.image = chatItem.picImage;
- cell.leftPicImage.hidden = YES;
- cell.rightPicImage.hidden = NO;
- cell.leftVideoButton.hidden = YES;
- cell.rightVideoButton.hidden = YES;
- NSLog(@"self send");
- }
- else if(chatItem.states == textStates)
- {
- cell.rightPicImage.hidden = YES;
- cell.leftPicImage.hidden = YES;
- cell.lefeView.hidden = YES;
- cell.rightView.hidden = NO;
- cell.leftVideoButton.hidden = YES;
- cell.rightVideoButton.hidden = YES;
- // 复用机制
- cell.rightLabel.frame = CGRectMake(10, 5, size.width, size.height);
- cell.rightView.frame = CGRectMake(WIDTH - 40 -size.width-25, 5, size.width + 25, size.height + 18);
- cell.rightLabel.text = chatItem.content;
- }
- else
- {
- cell.rightView.hidden = YES;
- cell.lefeView.hidden = YES;
- cell.rightView.hidden = YES;
- cell.lefeView.hidden = YES;
- cell.leftVideoButton.hidden = YES;
- cell.rightVideoButton.hidden = NO;
- cell.rightVideoButton.tag = 300 + indexPath.row;
- [cell.rightVideoButton addTarget:self action:@selector(cellSelectIndex:) forControlEvents:UIControlEventTouchUpInside];
- [cell.rightVideoButton setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];
- }
- }
- else // 接受得到
- {
- cell.leftHeadImage.hidden = NO;
- cell.rightHeadImage.hidden = YES;
- if(chatItem.states == picStates)
- {
- cell.rightView.hidden = YES;
- cell.lefeView.hidden = YES;
- cell.leftVideoButton.hidden = YES;
- cell.rightVideoButton.hidden = YES;
- cell.leftPicImage.image = chatItem.picImage;
- cell.rightPicImage.hidden = YES;
- cell.leftPicImage.hidden = NO;
- }
- else if(chatItem.states == textStates)
- {
- cell.rightPicImage.hidden = YES;
- cell.leftPicImage.hidden = YES;
- cell.rightView.hidden = YES;
- cell.lefeView.hidden = NO;
- cell.leftVideoButton.hidden = YES;
- cell.rightVideoButton.hidden = YES;
- cell.leftLabel.frame = CGRectMake(15, 5, size.width, size.height);
- cell.lefeView.frame = CGRectMake(40, 5, size.width +30, size.height + 25);
- cell.leftLabel.text = chatItem.content;
- }
- else
- {
- cell.rightView.hidden = YES;
- cell.lefeView.hidden = YES;
- cell.rightView.hidden = YES;
- cell.lefeView.hidden = YES;
- cell.leftVideoButton.hidden = NO;
- cell.rightVideoButton.hidden = YES;
- cell.leftVideoButton.tag = 300 + indexPath.row;
- [cell.leftVideoButton setImage:[UIImage imageNamed:@"record.png"] forState:UIControlStateNormal];
- [cell.leftVideoButton addTarget:self action:@selector(cellSelectIndex:) forControlEvents:UIControlEventTouchUpInside];
- }
- }
- return cell;
- }
- - (void)cellSelectIndex:(UIButton *)cellBtn
- {
- ChatItem *chatIden = [self.datasource objectAtIndex:cellBtn.tag - 300];
- if(chatIden.states == videoStates)
- {
- NSLog(@"realy play");
- // [self makeVideoPlayer:[self getVideoStremData]];
- [self makeVideoPlayer:chatIden.recordData];
- }
- }
- #pragma mark 下面是核心的连接MCSession 和 数据返回的地方
- /***************************-------**********************************************/
- - (void)makeBlueData
- {
- // 这是为了让 在block中弱引用
- __weak typeof (self) weakSelf = self;
- self.datasource = [NSMutableArray arrayWithCapacity:0];
- // 初始化 会议室
- self.sessionManager = [[BlueSessionManager alloc]initWithDisplayName:[NSString stringWithFormat:@" %@", [[UIDevice currentDevice] name]]];
- //
- [self.sessionManager didReceiveInvitationFromPeer:^void(MCPeerID *peer, NSData *context) {
- __strong typeof (weakSelf) strongSelf = weakSelf;
- UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"是否连接?" message:[NSString stringWithFormat:@"同 %@%@", peer.displayName, @" 连接?"] delegate:strongSelf cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil nil];
- [alertView show];
- }];
- [self.sessionManager peerConnectionStatusOnMainQueue:YES block:^(MCPeerID *peer, MCSessionState state) {
- if(state == MCSessionStateConnected) {
- UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"已经连接" message:[NSString stringWithFormat:@"现在连接 %@了!", peer.displayName] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];
- [alertView show];
- }
- }];
- // 发正常数据的返回
- [self.sessionManager receiveDataOnMainQueue:YES block:^(NSData *data, MCPeerID *peer) {
- __strong typeof (weakSelf) strongSelf = weakSelf;
- NSString *string = [NSKeyedUnarchiver unarchiveObjectWithData:data];
- ChatItem * chatItem = [[ChatItem alloc] init];
- chatItem.isSelf = NO;
- chatItem.states = textStates;
- chatItem.content = string;
- [strongSelf.datasource addObject:chatItem];
- // 加到数组里面
- [strongSelf insertTheTableToButtom];
- }];
- // 发图片之后的返回
- [self.sessionManager receiveFinalResourceOnMainQueue:YES complete:^(NSString *name, MCPeerID *peer, NSURL *url, NSError *error) {
- __strong typeof (weakSelf) strongSelf = weakSelf;
- NSData *data = [NSData dataWithContentsOfURL:url];
- ChatItem * chatItem = [[ChatItem alloc] init];
- chatItem.isSelf = NO;
- chatItem.states = picStates;
- chatItem.content = name;
- chatItem.picImage = [UIImage imageWithData:data];
- [strongSelf.datasource addObject:chatItem];
- [strongSelf insertTheTableToButtom];
- }];
- // 流
- [self.sessionManager didReceiveStreamFromPeer:^(NSInputStream *stream, MCPeerID *peer, NSString *streamName) {
- __strong typeof (weakSelf) strongSelf = weakSelf;
- strongSelf.inputStream = stream;
- strongSelf.inputStream.delegate = self;
- [strongSelf.inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
- [strongSelf.inputStream open];
- NSLog(@"we need");
- }];
- }
- - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
- {
- [self.sessionManager connectToPeer:buttonIndex == 1];
- }
- #pragma mark 下面是流的传输
- /***********--------------------- 下面是流的传输 ------------------------***********************************/
- - (void)videoRecord
- {
- // 播放录音
- [self SetTempRecordView];
- }
- - (void)sendAsStream
- {
- if(!self.sessionManager.isConnected)
- {
- UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"蓝牙已经断开了,请重新连接!" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:@"知道了", nil nil];
- [alertView show];
- return;
- }
- NSError *err;
- self.outputStream = [self.sessionManager streamWithName:@"super stream" toPeer:self.sessionManager.firstPeer error:&err];
- self.outputStream.delegate = self;
- [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
- if(err || !self.outputStream) {
- NSLog(@"%@", err);
- }
- else
- {
- [self.outputStream open];
- }
- }
- // 下面是一个代理
- - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
- {
- if(eventCode == NSStreamEventHasBytesAvailable)
- {
- // 有可读的字节,接收到了数据
- NSInputStream *input = (NSInputStream *)aStream;
- uint8_t buffer[1024];
- NSInteger length = [input read:buffer maxLength:1024];
- [self.streamData appendBytes:(const voidvoid *)buffer length:(NSUInteger)length];
- // 记住这边的数据陆陆续续的
- }
- else if(eventCode == NSStreamEventHasSpaceAvailable)
- {
- // 可以使用输出流的空间,此时可以发送数据给服务器
- // 发送数据的
- NSData *data = [self getVideoStremData];
- ChatItem * chatItem = [[ChatItem alloc] init];
- chatItem.isSelf = YES;
- chatItem.states = videoStates;
- chatItem.recordData = data;
- [self.datasource addObject:chatItem];
- [self insertTheTableToButtom];
- NSOutputStream *output = (NSOutputStream *)aStream;
- [output write:data.bytes maxLength:data.length];
- [output close];
- }
- if(eventCode == NSStreamEventEndEncountered)
- {
- // 流结束事件,在此事件中负责做销毁工作
- // 同时也是获得最终数据的好地方
- ChatItem * chatItem = [[ChatItem alloc] init];
- chatItem.isSelf = NO;
- chatItem.states = videoStates;
- chatItem.recordData = self.streamData;
- [self.datasource addObject:chatItem];
- [self insertTheTableToButtom];
- [aStream close];
- [aStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
- if([aStream isKindOfClass:[NSInputStream class]])
- {
- self.streamData = nil;
- }
- }
- if(eventCode == NSStreamEventErrorOccurred)
- {
- // 发生错误
- NSLog(@"error");
- }
- }
- - (NSMutableData *)streamData
- {
- if(!_streamData) {
- _streamData = [NSMutableData data];
- }
- return _streamData;
- }
- /***********----------------------- 公用的数据 --------------------***********************************/
- - (NSData *)imageData
- {
- return [NSData dataWithContentsOfURL:[self imageURL]];
- }
- - (NSURL *)imageURL {
- NSString *path = [[NSBundle mainBundle]pathForResource:@"301-alien-ship@2x" ofType:@"png"];
- // 这儿有个技术点
- // 那个如何将 image转化成 路径
- NSURL *url = [NSURL fileURLWithPath:path];
- return url;
- }
- /***********----------------------------------------------***********************************/
- #pragma mark 尝试空白处的连接
- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- {
- UITouch * touch = [[event allTouches] anyObject];
- if(touch.tapCount >= 1)
- {
- [self.sendTextView resignFirstResponder];
- }
- }
- /***********-------------------语音---------------------------***********************************/
- #pragma mark 尝试语音的录制和播出
- - (void)buildVideoForWe
- {
- // 设置录音会话
- [self setAudioSession];
- }
- - (void)SetTempRecordView
- {
- _backRemindRecordView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, 150)];
- _backRemindRecordView.center = self.view.center;
- _backRemindRecordView.backgroundColor = [UIColor lightGrayColor];
- [self.view addSubview:_backRemindRecordView];
- UILabel * beginLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 50, WIDTH -120, 50)];
- beginLabel.backgroundColor = [UIColor greenColor];
- beginLabel.text = @"长按录音开始···";
- beginLabel.tag = 1001;
- beginLabel.textAlignment = NSTextAlignmentCenter;
- beginLabel.userInteractionEnabled = YES;
- [_backRemindRecordView addSubview:beginLabel];
- UILongPressGestureRecognizer * longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressNextDo:)];
- [beginLabel addGestureRecognizer:longPress];
- }
- - (void)longPressNextDo:(UILongPressGestureRecognizer * )longPress
- {
- if(longPress.state == UIGestureRecognizerStateBegan)
- {
- NSLog(@"begin");
- UILabel * label = (UILabel *)[_backRemindRecordView viewWithTag:1001];
- label.text = @"录音正在进行中···";
- label.backgroundColor = [UIColor orangeColor];
- [self BeginRecordClick];
- }
- if(longPress.state == UIGestureRecognizerStateEnded)
- {
- [self OkStopClick];
- [_backRemindRecordView removeFromSuperview];
- [self sendAsStream];
- NSLog(@"stop");
- }
- }
- #pragma mark - 私有方法
- /**
- * 设置音频会话
- */
- -(void)setAudioSession
- {
- AVAudioSession *audioSession=[AVAudioSession sharedInstance];
- //设置为播放和录音状态,以便可以在录制完之后播放录音
- [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
- [audioSession setActive:YES error:nil];
- }
- /**
- * 取得录音文件保存路径
- *
- * @return 录音文件路径
- */
- -(NSURL *)getSavePath
- {
- NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
- urlStr=[urlStr stringByAppendingPathComponent:kRecordAudioFile];
- NSLog(@"file path:%@",urlStr);
- NSURL *url=[NSURL fileURLWithPath:urlStr];
- return url;
- }
- - (NSData *)getVideoStremData
- {
- return [NSData dataWithContentsOfURL:[self getSavePath]];
- }
- /**
- * 取得录音文件设置
- *
- * @return 录音设置
- */
- -(NSDictionary *)getAudioSetting{
- NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
- //设置录音格式
- [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
- //设置录音采样率,8000是电话采样率,对于一般录音已经够了
- [dicM setObject:@(8000) forKey:AVSampleRateKey];
- //设置通道,这里采用单声道
- [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
- //每个采样点位数,分为8、16、24、32
- [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
- //是否使用浮点数采样
- [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
- //....其他设置等
- return dicM;
- }
- /**
- * 获得录音机对象
- *
- * @return 录音机对象
- */
- -(AVAudioRecorder *)audioRecorder
- {
- if (!_audioRecorder) {
- //创建录音文件保存路径
- NSURL *url=[self getSavePath];
- //创建录音格式设置
- NSDictionary *setting=[self getAudioSetting];
- //创建录音机
- NSError *error=nil;
- _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
- _audioRecorder.delegate=self;
- _audioRecorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES
- if (error) {
- NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
- return nil;
- }
- }
- return _audioRecorder;
- }
- /**
- * 创建播放器
- *
- * @return 播放器
- */
- - (void)makeVideoPlayer:(NSData *)data
- {
- NSError *error=nil;
- self.audioPlayer=[[AVAudioPlayer alloc]initWithData:data error:&error];
- self.audioPlayer.delegate = self;
- self.audioPlayer.numberOfLoops=0;
- [self.audioPlayer prepareToPlay];
- if (error)
- {
- NSLog(@"创建播放器过程中发生错误,错误信息:%@",error.localizedDescription);
- }
- else
- {
- if (![self.audioPlayer isPlaying]) {
- NSLog(@"play");
- [self.audioPlayer play];
- }
- }
- }
- /**
- * 录音声波监控定制器
- *
- * @return 定时器
- */
- -(NSTimer *)timer{
- if (!_timer) {
- _timer=[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES];
- }
- return _timer;
- }
- /**
- * 录音声波状态设置
- */
- -(void)audioPowerChange{
- [self.audioRecorder updateMeters];//更新测量值
- float power= [self.audioRecorder averagePowerForChannel:0];//取得第一个通道的音频,注意音频强度范围时-160到0
- CGFloat progress=(1.0/160.0)*(power+160.0);
- [self.audioPower setProgress:progress];
- }
- #pragma mark - UI事件
- /**
- * 点击录音按钮
- *
- * @param sender 录音按钮
- */
- - (void)BeginRecordClick
- {
- if (![self.audioRecorder isRecording])
- {
- [self.audioRecorder record];//首次使用应用时如果调用record方法会询问用户是否允许使用麦克风
- self.timer.fireDate=[NSDate distantPast];
- }
- }
- /**
- * 点击暂定按钮
- *
- * @param sender 暂停按钮
- */
- - (void)StopPauseClick
- {
- if ([self.audioRecorder isRecording]) {
- [self.audioRecorder pause];
- self.timer.fireDate=[NSDate distantFuture];
- }
- }
- /**
- * 点击停止按钮
- *
- * @param sender 停止按钮
- */
- - (void)OkStopClick
- {
- [self.audioRecorder stop];
- self.timer.fireDate=[NSDate distantFuture];
- self.audioPower.progress=0.0;
- }
- #pragma mark - 录音机代理方法
- /**
- * 录音完成,录音完成后播放录音
- *
- * @param recorder 录音机对象
- * @param flag 是否成功
- */
- -(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
- {
- // if (![self.audioPlayer isPlaying]) {
- // [self.audioPlayer play];
- // }
- NSLog(@"录音完成!");
- }
- - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
- {
- // 每次完成后都将这个对象释放
- player =nil;
- }
建一个model类:
[objc] view plain copy
- .h
- #import <UIKit/UIKit.h>
- //@protocol CellSelectIndex <NSObject>
- //
- //- (void)cellSelectIndex;
- //
- //@end
- @interface ChatCell : UITableViewCell
- @property(nonatomic,strong)UIImageView * lefeView;
- @property(nonatomic,strong)UIImageView * rightView;
- @property(nonatomic,strong)UILabel * leftLabel;
- @property(nonatomic,strong)UILabel * rightLabel;
- @property(nonatomic,strong)UIImageView * leftHeadImage;
- @property(nonatomic,strong)UIImageView * rightHeadImage;
- @property(nonatomic,strong)UIImageView * leftPicImage;
- @property(nonatomic,strong)UIImageView * rightPicImage;
- @property(nonatomic ,strong)UIButton * leftVideoButton;
- @property(nonatomic, strong)UIButton * rightVideoButton;
- //@property(nonatomic,weak)id <CellSelectIndex> delegate;
- // 不能用名字相同的属性
- // 记住自动的时候,讲一下 weak and strong
- @end
- .m
- #import "ChatCell.h"
- @implementation ChatCell
- - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
- {
- self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
- if (self) {
- // Initialization code
- [self makeView];
- }
- return self;
- }
- -(void)makeView
- {
- UIImage * leftImgae = [UIImage imageNamed:@"ReceiverTextNodeBkg.png"];
- UIImage * rightImage = [UIImage imageNamed:@"SenderTextNodeBkg.png"];
- //这里设定一行一像素 当图片拉伸的时候,只放大两个像素
- leftImgae = [leftImgae stretchableImageWithLeftCapWidth:30 topCapHeight:35];
- // 找一行一列的像素
- rightImage = [rightImage stretchableImageWithLeftCapWidth:30 topCapHeight:35];
- // 设定完了后生成了一个新的image;
- //----------------------------------------------------------------------------------------//
- // 左边头像
- self.leftHeadImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 30, 30)];
- self.leftHeadImage.layer.masksToBounds = YES;
- self.leftHeadImage.layer.cornerRadius = 12;
- self.leftHeadImage.image = [UIImage imageNamed:@"f-pCert.png"];
- [self.contentView addSubview:self.leftHeadImage];
- //左边气泡
- self.leftVideoButton = [UIButton buttonWithType:UIButtonTypeCustom];
- self.leftVideoButton.frame = CGRectMake(40, 5, 35, 35);
- // [self.leftVideoButton addTarget:self action:@selector(recordTheVoice) forControlEvents:UIControlEventTouchUpInside];
- [self.contentView addSubview:self.leftVideoButton];
- self.leftPicImage = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 66, 30)];
- [self.contentView addSubview:self.leftPicImage];
- self.lefeView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 66, 30)];
- self.lefeView.image = leftImgae;
- // 这里不是一个小像素的图片??
- [self.contentView addSubview:self.lefeView];
- self.leftLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 5, 1, 1)];
- self.leftLabel.font = [UIFont systemFontOfSize:14];
- self.leftLabel.numberOfLines = 0; // 换行
- self.leftLabel.backgroundColor = [UIColor clearColor];// 设置透明的
- [self.lefeView addSubview:self.leftLabel];
- //----------------------------------------------------------------------------------------//
- self.rightHeadImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 35, 5, 30, 30)];
- self.rightHeadImage.layer.masksToBounds = YES;
- self.rightHeadImage.layer.cornerRadius = 12;
- self.rightHeadImage.image = [UIImage imageNamed:@"f-plove.png"];
- [self.contentView addSubview:self.rightHeadImage];
- self.rightVideoButton = [UIButton buttonWithType:UIButtonTypeCustom];
- self.rightVideoButton.frame = CGRectMake(self.frame.size.width - 45 - 40, 5, 35, 35);
- // [self.rightVideoButton addTarget:self action:@selector(recordTheVoice) forControlEvents:UIControlEventTouchUpInside];
- [self.contentView addSubview:self.rightVideoButton];
- self.rightPicImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 45 - 30, 5, 30, 30)];
- [self.contentView addSubview:self.rightPicImage];
- // 右边
- self.rightView = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - (66+40), 5, 66, 30)];
- self.rightView.image = rightImage;
- [self.contentView addSubview:self.rightView];
- self.rightLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 1, 1)];
- self.rightLabel.font = [UIFont systemFontOfSize:14];
- self.rightLabel.backgroundColor = [UIColor clearColor];
- self.rightLabel.numberOfLines = 0;
- [self.rightView addSubview:self.rightLabel];
- }
- //- (void)recordTheVoice
- //{
- // [self.delegate cellSelectIndex];
- //}
每日更新关注:http://weibo.com/hanjunqiang 新浪微博
基本知识必须了解的
MCAdvertiserAssistant //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。
MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。
MCNearbyServiceBrowser //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。
MCPeerID //这表明是一个用户
MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。
建一个类用来写所有方法:
[objc] view plain copy
- .h
- #import <Foundation/Foundation.h>
- @import MultipeerConnectivity;
- @interface BlueSessionManager : NSObject
- @property(strong, nonatomic, readonly) NSArray *connectedPeers;
- @property(strong, nonatomic, readonly) MCSession *session;
- @property(nonatomic, readonly, getter = isConnected) BOOL connected;
- @property(strong, nonatomic) NSDictionary *discoveryInfo; // 发现设备的特征
- @property(strong, nonatomic, readonly) MCPeerID *firstPeer; // 第一个连接的 用户
- /**
- * The service type provided for browsing and advertising.
- * This should be a short text string that describes the
- * app's networking protocol. Should be something
- * in the form of `tjl_appname`.
- */
- @property(strong, nonatomic) NSString *serviceType;
- /*
- 初始化一个 假设的用户名字
- */
- - (instancetype)__attribute__((nonnull(1)))initWithDisplayName:(NSString *)displayName;
- - (void)browseForProgrammaticDiscovery;
- - (void)advertiseForBrowserViewController;
- - (void)advertiseForProgrammaticDiscovery;
- - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
- - (NSError *)sendDataToAllPeers:(NSData *)data;
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers;
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode;
- - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock;
- - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete;
- - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block;
- - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block;
- - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error;
- - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock;
- - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status;
- - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled;
- - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found;
- - (void)connectToPeer:(BOOL)connect;
- // 邀请其他设备连接
- - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected;
- - (void)disconnectSession;
- // 停止打开自己
- - (void)stopAdvertising;
- // 停止扫描
- - (void)stopBrowsing;
- @end
- .m
- #import "BlueSessionManager.h"
- #define ServiceType @"MyService"
- /*
- MCAdvertiserAssistant //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。
- MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。
- MCNearbyServiceBrowser //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。
- MCPeerID //这表明是一个用户
- MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。
- */
- @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>
- @property(strong, nonatomic) MCSession *currentSession; // 当前会议
- @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手
- @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手
- @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者
- @property(strong, nonatomic) MCPeerID *peerID; // 用户
- // 以下都是用到的block
- @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
- @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
- @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
- @property(nonatomic, copy) void(^browserConnected)(void);
- @property(nonatomic, copy) void(^browserCancelled)(void);
- @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
- @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
- @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
- @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
- @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
- @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
- // 各种判断
- @property(nonatomic, assign) BOOL receiveOnMainQueue;
- @property(nonatomic, assign) BOOL statusOnMainQueue;
- @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
- @property(nonatomic, assign) BOOL resourceStart;
- @end
- @implementation BlueSessionManager
- #pragma mark 初始化自己
- - (instancetype)initWithDisplayName:(NSString *)displayName
- {
- return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
- }
- // 为上面自定义 用户
- - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
- {
- self = [super init];
- if(!self) {
- return nil;
- }
- self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
- self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
- self.session.delegate = self;
- self.serviceType = type;
- return self;
- }
- #pragma mark 宣传自己
- - (void)advertiseForBrowserViewController
- {
- [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
- }
- - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
- {
- //
- self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
- self.advertiser.delegate = self;
- [self.advertiser startAdvertisingPeer];
- }
- - (void)advertiseForProgrammaticDiscovery
- {
- [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
- }
- - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
- {
- //自定义自己,为了让其他设备搜索到自己
- self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
- self.advertisingAssistant.delegate = self;
- [self.advertisingAssistant start];
- }
- - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
- self.invitationHandler = [invitationHandler copy];
- if(self.inviteBlock) self.inviteBlock(peerID, context);
- }
- #pragma mark 下面是MCAdvertiserAssistant的两个代理
- - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
- {
- //TODO implement
- }
- - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
- //TODO implement
- }
- #pragma mark 扫描其他的设备
- - (void)browseForProgrammaticDiscovery
- {
- self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
- self.browser.delegate = self;
- [self.browser startBrowsingForPeers];
- }
- #pragma mark MCNearbyServiceBrowserDelegate
- - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
- {
- //TODO implement
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
- {
- if(self.didFindPeer)
- {
- self.didFindPeer(peerID, info);
- }
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
- {
- //TODO implement
- }
- #pragma mark 参加会议 也是会议的代理
- // 也是 ----- MCSessionDelegate
- // 这是完成会议的结果···
- - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
- {
- if(self.resourceFinalOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }];
- }
- else
- {
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }
- }
- // 这是参加 普通数据的会议
- - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
- {
- if(self.receiveOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.receiveDataBlock){
- self.receiveDataBlock(data, peerID);
- }
- }];
- }
- else
- {
- if(self.receiveDataBlock)
- {
- self.receiveDataBlock(data, peerID);
- }
- }
- }
- // 这是参加普通流的会议
- - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
- {
- if(self.streamBlock)
- {
- self.streamBlock(stream, peerID, streamName);
- }
- }
- // 这是参加图片资源的会议
- - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
- {
- if(self.resourceStart)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }];
- }
- else
- {
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }
- }
- // 这是不同数据,系那是不同会议时候的状态
- - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
- {
- // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议
- if(self.statusOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }];
- }
- else
- {
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }
- }
- #pragma mark send And receive
- //--------------------------------------------------------------------------------------------//
- // 发送消息
- // 用户多个
- - (NSError *)sendDataToAllPeers:(NSData *)data
- {
- // 普通数据的发送
- return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
- {
- // 确实进入会议
- NSError *error;
- [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
- return error;
- }
- // 用户确定一个
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
- {
- return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
- {
- NSError *error;
- [self.session sendData:data toPeers:peers withMode:mode error:&error];
- return error;
- }
- // 接收消息
- - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
- {
- self.receiveDataBlock = [dataBlock copy];
- self.receiveOnMainQueue = mainQueue;
- }
- //--------------------------------------------------------------------------------------------//
- - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
- {
- // 图片资源数据的发送
- return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
- }
- // 用户连接确定
- - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
- {
- self.connectionStatus = [status copy];
- self.statusOnMainQueue = mainQueue;
- }
- #pragma mark 自带的MCBrowserViewController类
- - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserConnected) self.browserConnected();
- }];
- }
- - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserCancelled) self.browserCancelled();
- }];
- }
- - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
- {
- self.browserConnected = [connected copy];
- self.browserCancelled = [cancelled copy];
- // 注意这个自带的类
- MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
- browser.delegate = self;
- [controller presentViewController:browser animated:YES completion:nil];
- }
- - (NSArray *)connectedPeers
- {
- return self.session.connectedPeers;
- }
- // 邀请某某连接
- - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
- {
- self.inviteBlock = [invite copy];
- }
- - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
- {
- [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
- }
- - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
- {
- self.didStartReceivingResource = [block copy];
- self.resourceStart = mainQueue;
- }
- // 接收某某资源
- - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
- {
- self.finalResource = [block copy];
- self.resourceFinalOnMainQueue = mainQueue;
- }
- - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
- {
- return [self.session startStreamWithName:name toPeer:peerID error:error];
- }
- // 开始转化为流
- - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
- {
- self.streamBlock = [streamBlock copy];
- }
- - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
- {
- self.didFindPeer = [found copy];
- }
- #pragma mark 一些断开的情况
- - (void)disconnectSession
- {
- [self.session disconnect];
- }
- - (void)stopAdvertising
- {
- [self.advertiser stopAdvertisingPeer];
- [self.advertisingAssistant stop];
- }
- - (void)stopBrowsing
- {
- [self.browser stopBrowsingForPeers];
- }
- - (BOOL)isConnected {
- return self.session.connectedPeers && self.session.connectedPeers.count > 0;
- }
- // 是否连接 它
- - (void)connectToPeer:(BOOL)connect {
- self.invitationHandler(connect, self.session);
- }
- - (MCSession *)session {
- return self.currentSession;
- }
- - (MCPeerID *)firstPeer {
- return self.session.connectedPeers.firstObject;
- }
- @end
- #import "BlueSessionManager.h"
- #define ServiceType @"MyService"
- /*
- MCAdvertiserAssistant //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。
- MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。
- MCNearbyServiceBrowser //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。
- MCPeerID //这表明是一个用户
- MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。
- */
- @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>
- @property(strong, nonatomic) MCSession *currentSession; // 当前会议
- @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手
- @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手
- @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者
- @property(strong, nonatomic) MCPeerID *peerID; // 用户
- // 以下都是用到的block
- @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
- @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
- @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
- @property(nonatomic, copy) void(^browserConnected)(void);
- @property(nonatomic, copy) void(^browserCancelled)(void);
- @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
- @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
- @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
- @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
- @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
- @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
- // 各种判断
- @property(nonatomic, assign) BOOL receiveOnMainQueue;
- @property(nonatomic, assign) BOOL statusOnMainQueue;
- @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
- @property(nonatomic, assign) BOOL resourceStart;
- @end
- @implementation BlueSessionManager
- #pragma mark 初始化自己
- - (instancetype)initWithDisplayName:(NSString *)displayName
- {
- return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
- }
- // 为上面自定义 用户
- - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
- {
- self = [super init];
- if(!self) {
- return nil;
- }
- self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
- self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
- self.session.delegate = self;
- self.serviceType = type;
- return self;
- }
- #pragma mark 宣传自己
- - (void)advertiseForBrowserViewController
- {
- [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
- }
- - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
- {
- //
- self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
- self.advertiser.delegate = self;
- [self.advertiser startAdvertisingPeer];
- }
- - (void)advertiseForProgrammaticDiscovery
- {
- [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
- }
- - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
- {
- //自定义自己,为了让其他设备搜索到自己
- self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
- self.advertisingAssistant.delegate = self;
- [self.advertisingAssistant start];
- }
- - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
- self.invitationHandler = [invitationHandler copy];
- if(self.inviteBlock) self.inviteBlock(peerID, context);
- }
- #pragma mark 下面是MCAdvertiserAssistant的两个代理
- - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
- {
- //TODO implement
- }
- - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
- //TODO implement
- }
- #pragma mark 扫描其他的设备
- - (void)browseForProgrammaticDiscovery
- {
- self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
- self.browser.delegate = self;
- [self.browser startBrowsingForPeers];
- }
- #pragma mark MCNearbyServiceBrowserDelegate
- - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
- {
- //TODO implement
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
- {
- if(self.didFindPeer)
- {
- self.didFindPeer(peerID, info);
- }
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
- {
- //TODO implement
- }
- #pragma mark 参加会议 也是会议的代理
- // 也是 ----- MCSessionDelegate
- // 这是完成会议的结果···
- - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
- {
- if(self.resourceFinalOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }];
- }
- else
- {
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }
- }
- // 这是参加 普通数据的会议
- - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
- {
- if(self.receiveOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.receiveDataBlock){
- self.receiveDataBlock(data, peerID);
- }
- }];
- }
- else
- {
- if(self.receiveDataBlock)
- {
- self.receiveDataBlock(data, peerID);
- }
- }
- }
- // 这是参加普通流的会议
- - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
- {
- if(self.streamBlock)
- {
- self.streamBlock(stream, peerID, streamName);
- }
- }
- // 这是参加图片资源的会议
- - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
- {
- if(self.resourceStart)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }];
- }
- else
- {
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }
- }
- // 这是不同数据,系那是不同会议时候的状态
- - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
- {
- // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议
- if(self.statusOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }];
- }
- else
- {
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }
- }
- #pragma mark send And receive
- //--------------------------------------------------------------------------------------------//
- // 发送消息
- // 用户多个
- - (NSError *)sendDataToAllPeers:(NSData *)data
- {
- // 普通数据的发送
- return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
- {
- // 确实进入会议
- NSError *error;
- [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
- return error;
- }
- // 用户确定一个
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
- {
- return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
- {
- NSError *error;
- [self.session sendData:data toPeers:peers withMode:mode error:&error];
- return error;
- }
- // 接收消息
- - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
- {
- self.receiveDataBlock = [dataBlock copy];
- self.receiveOnMainQueue = mainQueue;
- }
- //--------------------------------------------------------------------------------------------//
- - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
- {
- // 图片资源数据的发送
- return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
- }
- // 用户连接确定
- - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
- {
- self.connectionStatus = [status copy];
- self.statusOnMainQueue = mainQueue;
- }
- #pragma mark 自带的MCBrowserViewController类
- - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserConnected) self.browserConnected();
- }];
- }
- - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserCancelled) self.browserCancelled();
- }];
- }
- - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
- {
- self.browserConnected = [connected copy];
- self.browserCancelled = [cancelled copy];
- // 注意这个自带的类
- MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
- browser.delegate = self;
- [controller presentViewController:browser animated:YES completion:nil];
- }
- - (NSArray *)connectedPeers
- {
- return self.session.connectedPeers;
- }
- // 邀请某某连接
- - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
- {
- self.inviteBlock = [invite copy];
- }
- - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
- {
- [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
- }
- - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
- {
- self.didStartReceivingResource = [block copy];
- self.resourceStart = mainQueue;
- }
- // 接收某某资源
- - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
- {
- self.finalResource = [block copy];
- self.resourceFinalOnMainQueue = mainQueue;
- }
- - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
- {
- return [self.session startStreamWithName:name toPeer:peerID error:error];
- }
- // 开始转化为流
- - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
- {
- self.streamBlock = [streamBlock copy];
- }
- - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
- {
- self.didFindPeer = [found copy];
- }
- #pragma mark 一些断开的情况
- - (void)disconnectSession
- {
- [self.session disconnect];
- }
- - (void)stopAdvertising
- {
- [self.advertiser stopAdvertisingPeer];
- [self.advertisingAssistant stop];
- }
- - (void)stopBrowsing
- {
- [self.browser stopBrowsingForPeers];
- }
- - (BOOL)isConnected {
- return self.session.connectedPeers && self.session.connectedPeers.count > 0;
- }
- // 是否连接 它
- - (void)connectToPeer:(BOOL)connect {
- self.invitationHandler(connect, self.session);
- }
- - (MCSession *)session {
- return self.currentSession;
- }
- - (MCPeerID *)firstPeer {
- return self.session.connectedPeers.firstObject;
- }
- @end
- #import "BlueSessionManager.h"
- #define ServiceType @"MyService"
- /*
- MCAdvertiserAssistant //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。
- MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。
- MCNearbyServiceBrowser //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。
- MCPeerID //这表明是一个用户
- MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。
- */
- @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>
- @property(strong, nonatomic) MCSession *currentSession; // 当前会议
- @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手
- @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手
- @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者
- @property(strong, nonatomic) MCPeerID *peerID; // 用户
- // 以下都是用到的block
- @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
- @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
- @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
- @property(nonatomic, copy) void(^browserConnected)(void);
- @property(nonatomic, copy) void(^browserCancelled)(void);
- @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
- @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
- @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
- @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
- @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
- @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
- // 各种判断
- @property(nonatomic, assign) BOOL receiveOnMainQueue;
- @property(nonatomic, assign) BOOL statusOnMainQueue;
- @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
- @property(nonatomic, assign) BOOL resourceStart;
- @end
- @implementation BlueSessionManager
- #pragma mark 初始化自己
- - (instancetype)initWithDisplayName:(NSString *)displayName
- {
- return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
- }
- // 为上面自定义 用户
- - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
- {
- self = [super init];
- if(!self) {
- return nil;
- }
- self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
- self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
- self.session.delegate = self;
- self.serviceType = type;
- return self;
- }
- #pragma mark 宣传自己
- - (void)advertiseForBrowserViewController
- {
- [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
- }
- - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
- {
- //
- self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
- self.advertiser.delegate = self;
- [self.advertiser startAdvertisingPeer];
- }
- - (void)advertiseForProgrammaticDiscovery
- {
- [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
- }
- - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
- {
- //自定义自己,为了让其他设备搜索到自己
- self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
- self.advertisingAssistant.delegate = self;
- [self.advertisingAssistant start];
- }
- - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
- self.invitationHandler = [invitationHandler copy];
- if(self.inviteBlock) self.inviteBlock(peerID, context);
- }
- #pragma mark 下面是MCAdvertiserAssistant的两个代理
- - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
- {
- //TODO implement
- }
- - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
- //TODO implement
- }
- #pragma mark 扫描其他的设备
- - (void)browseForProgrammaticDiscovery
- {
- self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
- self.browser.delegate = self;
- [self.browser startBrowsingForPeers];
- }
- #pragma mark MCNearbyServiceBrowserDelegate
- - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
- {
- //TODO implement
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
- {
- if(self.didFindPeer)
- {
- self.didFindPeer(peerID, info);
- }
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
- {
- //TODO implement
- }
- #pragma mark 参加会议 也是会议的代理
- // 也是 ----- MCSessionDelegate
- // 这是完成会议的结果···
- - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
- {
- if(self.resourceFinalOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }];
- }
- else
- {
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }
- }
- // 这是参加 普通数据的会议
- - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
- {
- if(self.receiveOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.receiveDataBlock){
- self.receiveDataBlock(data, peerID);
- }
- }];
- }
- else
- {
- if(self.receiveDataBlock)
- {
- self.receiveDataBlock(data, peerID);
- }
- }
- }
- // 这是参加普通流的会议
- - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
- {
- if(self.streamBlock)
- {
- self.streamBlock(stream, peerID, streamName);
- }
- }
- // 这是参加图片资源的会议
- - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
- {
- if(self.resourceStart)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }];
- }
- else
- {
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }
- }
- // 这是不同数据,系那是不同会议时候的状态
- - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
- {
- // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议
- if(self.statusOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }];
- }
- else
- {
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }
- }
- #pragma mark send And receive
- //--------------------------------------------------------------------------------------------//
- // 发送消息
- // 用户多个
- - (NSError *)sendDataToAllPeers:(NSData *)data
- {
- // 普通数据的发送
- return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
- {
- // 确实进入会议
- NSError *error;
- [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
- return error;
- }
- // 用户确定一个
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
- {
- return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
- {
- NSError *error;
- [self.session sendData:data toPeers:peers withMode:mode error:&error];
- return error;
- }
- // 接收消息
- - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
- {
- self.receiveDataBlock = [dataBlock copy];
- self.receiveOnMainQueue = mainQueue;
- }
- //--------------------------------------------------------------------------------------------//
- - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
- {
- // 图片资源数据的发送
- return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
- }
- // 用户连接确定
- - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
- {
- self.connectionStatus = [status copy];
- self.statusOnMainQueue = mainQueue;
- }
- #pragma mark 自带的MCBrowserViewController类
- - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserConnected) self.browserConnected();
- }];
- }
- - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserCancelled) self.browserCancelled();
- }];
- }
- - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
- {
- self.browserConnected = [connected copy];
- self.browserCancelled = [cancelled copy];
- // 注意这个自带的类
- MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
- browser.delegate = self;
- [controller presentViewController:browser animated:YES completion:nil];
- }
- - (NSArray *)connectedPeers
- {
- return self.session.connectedPeers;
- }
- // 邀请某某连接
- - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
- {
- self.inviteBlock = [invite copy];
- }
- - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
- {
- [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
- }
- - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
- {
- self.didStartReceivingResource = [block copy];
- self.resourceStart = mainQueue;
- }
- // 接收某某资源
- - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
- {
- self.finalResource = [block copy];
- self.resourceFinalOnMainQueue = mainQueue;
- }
- - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
- {
- return [self.session startStreamWithName:name toPeer:peerID error:error];
- }
- // 开始转化为流
- - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
- {
- self.streamBlock = [streamBlock copy];
- }
- - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
- {
- self.didFindPeer = [found copy];
- }
- #pragma mark 一些断开的情况
- - (void)disconnectSession
- {
- [self.session disconnect];
- }
- - (void)stopAdvertising
- {
- [self.advertiser stopAdvertisingPeer];
- [self.advertisingAssistant stop];
- }
- - (void)stopBrowsing
- {
- [self.browser stopBrowsingForPeers];
- }
- - (BOOL)isConnected {
- return self.session.connectedPeers && self.session.connectedPeers.count > 0;
- }
- // 是否连接 它
- - (void)connectToPeer:(BOOL)connect {
- self.invitationHandler(connect, self.session);
- }
- - (MCSession *)session {
- return self.currentSession;
- }
- - (MCPeerID *)firstPeer {
- return self.session.connectedPeers.firstObject;
- }
- @end
- .m
- #import "BlueSessionManager.h"
- #define ServiceType @"MyService"
- /*
- MCAdvertiserAssistant //可以接收,并处理用户请求连接的响应。没有回调,会弹出默认的提示框,并处理连接。
- MCNearbyServiceAdvertiser //可以接收,并处理用户请求连接的响应。但是,这个类会有回调,告知有用户要与您的设备连接,然后可以自定义提示框,以及自定义连接处理。
- MCNearbyServiceBrowser //用于搜索附近的用户,并可以对搜索到的用户发出邀请加入某个会话中。
- MCPeerID //这表明是一个用户
- MCSession //启用和管理Multipeer连接会话中的所有人之间的沟通。 通过Sesion,给别人发送数据。
- */
- @interface BlueSessionManager ()<MCAdvertiserAssistantDelegate, MCNearbyServiceBrowserDelegate, MCSessionDelegate, MCBrowserViewControllerDelegate, MCNearbyServiceAdvertiserDelegate, UIAlertViewDelegate>
- @property(strong, nonatomic) MCSession *currentSession; // 当前会议
- @property(strong, nonatomic) MCAdvertiserAssistant *advertisingAssistant; // 宣传助手
- @property(strong, nonatomic) MCNearbyServiceAdvertiser *advertiser; // 服务助手
- @property(strong, nonatomic) MCNearbyServiceBrowser *browser; // 搜索蓝牙者
- @property(strong, nonatomic) MCPeerID *peerID; // 用户
- // 以下都是用到的block
- @property(nonatomic, copy) void(^receiveDataBlock)(NSData *data, MCPeerID *peer);
- @property(nonatomic, copy) void(^receiveResourceBlock)(MCPeerID *peer, NSURL *url);
- @property(nonatomic, copy) void(^connectionStatus)(MCPeerID *peer, MCSessionState state);
- @property(nonatomic, copy) void(^browserConnected)(void);
- @property(nonatomic, copy) void(^browserCancelled)(void);
- @property(nonatomic, copy) void(^didFindPeer)(MCPeerID *peer, NSDictionary *info);
- @property(nonatomic, copy) void(^invitationHandler)(BOOL connect, MCSession *session);
- @property(nonatomic, copy) void(^inviteBlock)(MCPeerID *peer, NSData *context);
- @property(nonatomic, copy) void(^didStartReceivingResource)(NSString *name, MCPeerID *peer, NSProgress *progress);
- @property(nonatomic, copy) void(^finalResource)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error);
- @property(nonatomic, copy) void(^streamBlock)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName);
- // 各种判断
- @property(nonatomic, assign) BOOL receiveOnMainQueue;
- @property(nonatomic, assign) BOOL statusOnMainQueue;
- @property(nonatomic, assign) BOOL resourceFinalOnMainQueue;
- @property(nonatomic, assign) BOOL resourceStart;
- @end
- @implementation BlueSessionManager
- #pragma mark 初始化自己
- - (instancetype)initWithDisplayName:(NSString *)displayName
- {
- return [self initWithDisplayName:displayName securityIdentity:nil encryptionPreferences:MCEncryptionNone serviceType:ServiceType];
- }
- // 为上面自定义 用户
- - (instancetype)initWithDisplayName:(NSString *)displayName securityIdentity:(NSArray *)security encryptionPreferences:(MCEncryptionPreference)preference serviceType:(NSString *)type
- {
- self = [super init];
- if(!self) {
- return nil;
- }
- self.peerID = [[MCPeerID alloc]initWithDisplayName:displayName];
- self.currentSession = [[MCSession alloc]initWithPeer:self.peerID securityIdentity:security encryptionPreference:preference];
- self.session.delegate = self;
- self.serviceType = type;
- return self;
- }
- #pragma mark 宣传自己
- - (void)advertiseForBrowserViewController
- {
- [self advertiseForBrowserViewControllerWithDiscoveryInfo:nil];
- }
- - (void)advertiseForBrowserViewControllerWithDiscoveryInfo:(NSDictionary *)info
- {
- //
- self.advertiser = [[MCNearbyServiceAdvertiser alloc]initWithPeer:self.peerID discoveryInfo:info serviceType:self.serviceType];
- self.advertiser.delegate = self;
- [self.advertiser startAdvertisingPeer];
- }
- - (void)advertiseForProgrammaticDiscovery
- {
- [self advertiseForProgrammaticDiscoveryWithDiscoveryInfo:nil];
- }
- - (void)advertiseForProgrammaticDiscoveryWithDiscoveryInfo:(NSDictionary *)info
- {
- //自定义自己,为了让其他设备搜索到自己
- self.advertisingAssistant = [[MCAdvertiserAssistant alloc]initWithServiceType:self.serviceType discoveryInfo:info session:self.session];
- self.advertisingAssistant.delegate = self;
- [self.advertisingAssistant start];
- }
- - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler {
- self.invitationHandler = [invitationHandler copy];
- if(self.inviteBlock) self.inviteBlock(peerID, context);
- }
- #pragma mark 下面是MCAdvertiserAssistant的两个代理
- - (void)advertiserAssistantDidDismissInvitation:(MCAdvertiserAssistant *)advertiserAssistant
- {
- //TODO implement
- }
- - (void)advertiserAssitantWillPresentInvitation:(MCAdvertiserAssistant *)advertiserAssistant {
- //TODO implement
- }
- #pragma mark 扫描其他的设备
- - (void)browseForProgrammaticDiscovery
- {
- self.browser = [[MCNearbyServiceBrowser alloc]initWithPeer:self.peerID serviceType:self.serviceType];
- self.browser.delegate = self;
- [self.browser startBrowsingForPeers];
- }
- #pragma mark MCNearbyServiceBrowserDelegate
- - (void)browser:(MCNearbyServiceBrowser *)browser lostPeer:(MCPeerID *)peerID
- {
- //TODO implement
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info
- {
- if(self.didFindPeer)
- {
- self.didFindPeer(peerID, info);
- }
- }
- - (void)browser:(MCNearbyServiceBrowser *)browser didNotStartBrowsingForPeers:(NSError *)error
- {
- //TODO implement
- }
- #pragma mark 参加会议 也是会议的代理
- // 也是 ----- MCSessionDelegate
- // 这是完成会议的结果···
- - (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error
- {
- if(self.resourceFinalOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }];
- }
- else
- {
- if(self.finalResource)
- {
- self.finalResource(resourceName, peerID, localURL, error);
- }
- }
- }
- // 这是参加 普通数据的会议
- - (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
- {
- if(self.receiveOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.receiveDataBlock){
- self.receiveDataBlock(data, peerID);
- }
- }];
- }
- else
- {
- if(self.receiveDataBlock)
- {
- self.receiveDataBlock(data, peerID);
- }
- }
- }
- // 这是参加普通流的会议
- - (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID
- {
- if(self.streamBlock)
- {
- self.streamBlock(stream, peerID, streamName);
- }
- }
- // 这是参加图片资源的会议
- - (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
- {
- if(self.resourceStart)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }];
- }
- else
- {
- if(self.didStartReceivingResource)
- {
- self.didStartReceivingResource(resourceName, peerID, progress);
- }
- }
- }
- // 这是不同数据,系那是不同会议时候的状态
- - (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
- {
- // 这个地方是当两个蓝牙设备一旦连接起来,就会形成的一个会议
- if(self.statusOnMainQueue)
- {
- [[NSOperationQueue mainQueue]addOperationWithBlock:^{
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }];
- }
- else
- {
- if(self.connectionStatus)
- {
- self.connectionStatus(peerID, state);
- }
- }
- }
- #pragma mark send And receive
- //--------------------------------------------------------------------------------------------//
- // 发送消息
- // 用户多个
- - (NSError *)sendDataToAllPeers:(NSData *)data
- {
- // 普通数据的发送
- return [self sendDataToAllPeers:data withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendDataToAllPeers:(NSData *)data withMode:(MCSessionSendDataMode)mode
- {
- // 确实进入会议
- NSError *error;
- [self.session sendData:data toPeers:self.session.connectedPeers withMode:mode error:&error];
- return error;
- }
- // 用户确定一个
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers
- {
- return [self sendData:data toPeers:peers withMode:MCSessionSendDataReliable];
- }
- - (NSError *)sendData:(NSData *)data toPeers:(NSArray *)peers withMode:(MCSessionSendDataMode)mode
- {
- NSError *error;
- [self.session sendData:data toPeers:peers withMode:mode error:&error];
- return error;
- }
- // 接收消息
- - (void)receiveDataOnMainQueue:(BOOL)mainQueue block:(void (^)(NSData *data, MCPeerID *peer))dataBlock
- {
- self.receiveDataBlock = [dataBlock copy];
- self.receiveOnMainQueue = mainQueue;
- }
- //--------------------------------------------------------------------------------------------//
- - (NSProgress *)sendResourceWithName:(NSString *)name atURL:(NSURL *)url toPeer:(MCPeerID *)peer complete:(void (^)(NSError *error))compelete
- {
- // 图片资源数据的发送
- return [self.session sendResourceAtURL:url withName:name toPeer:peer withCompletionHandler:compelete];
- }
- // 用户连接确定
- - (void)peerConnectionStatusOnMainQueue:(BOOL)mainQueue block:(void (^)(MCPeerID *peer, MCSessionState state))status
- {
- self.connectionStatus = [status copy];
- self.statusOnMainQueue = mainQueue;
- }
- #pragma mark 自带的MCBrowserViewController类
- - (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserConnected) self.browserConnected();
- }];
- }
- - (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController
- {
- [browserViewController dismissViewControllerAnimated:YES completion:^{
- if(self.browserCancelled) self.browserCancelled();
- }];
- }
- - (void)browseWithControllerInViewController:(UIViewController *)controller connected:(void (^)(void))connected canceled:(void (^)(void))cancelled
- {
- self.browserConnected = [connected copy];
- self.browserCancelled = [cancelled copy];
- // 注意这个自带的类
- MCBrowserViewController *browser = [[MCBrowserViewController alloc]initWithServiceType:self.serviceType session:self.session];
- browser.delegate = self;
- [controller presentViewController:browser animated:YES completion:nil];
- }
- - (NSArray *)connectedPeers
- {
- return self.session.connectedPeers;
- }
- // 邀请某某连接
- - (void)didReceiveInvitationFromPeer:(void (^)(MCPeerID *peer, NSData *context))invite;
- {
- self.inviteBlock = [invite copy];
- }
- - (void)invitePeerToConnect:(MCPeerID *)peer connected:(void (^)(void))connected
- {
- [self.browser invitePeer:peer toSession:self.session withContext:nil timeout:30];
- }
- - (void)startReceivingResourceOnMainQueue:(BOOL)mainQueue block:(void (^)(NSString *name, MCPeerID *peer, NSProgress *progress))block
- {
- self.didStartReceivingResource = [block copy];
- self.resourceStart = mainQueue;
- }
- // 接收某某资源
- - (void)receiveFinalResourceOnMainQueue:(BOOL)mainQueue complete:(void (^)(NSString *name, MCPeerID *peer, NSURL *url, NSError *error))block
- {
- self.finalResource = [block copy];
- self.resourceFinalOnMainQueue = mainQueue;
- }
- - (NSOutputStream *)streamWithName:(NSString *)name toPeer:(MCPeerID *)peerID error:(NSError * __autoreleasing *)error
- {
- return [self.session startStreamWithName:name toPeer:peerID error:error];
- }
- // 开始转化为流
- - (void)didReceiveStreamFromPeer:(void (^)(NSInputStream *inputStream, MCPeerID *peer, NSString *streamName))streamBlock
- {
- self.streamBlock = [streamBlock copy];
- }
- - (void)didFindPeerWithInfo:(void (^)(MCPeerID *peer, NSDictionary *info))found
- {
- self.didFindPeer = [found copy];
- }
- #pragma mark 一些断开的情况
- - (void)disconnectSession
- {
- [self.session disconnect];
- }
- - (void)stopAdvertising
- {
- [self.advertiser stopAdvertisingPeer];
- [self.advertisingAssistant stop];
- }
- - (void)stopBrowsing
- {
- [self.browser stopBrowsingForPeers];
- }
- - (BOOL)isConnected {
- return self.session.connectedPeers && self.session.connectedPeers.count > 0;
- }
- // 是否连接 它
- - (void)connectToPeer:(BOOL)connect {
- self.invitationHandler(connect, self.session);
- }
- - (MCSession *)session {
- return self.currentSession;
- }
- - (MCPeerID *)firstPeer {
- return self.session.connectedPeers.firstObject;
- }
- @end
最终效果只能真机测试,所以这里不做演示!
每日更新关注:http://weibo.com/hanjunqiang 新浪微博
原文地址:http://blog.csdn.net/qq_31810357/article/details/50204477