首页 > 代码库 > 【Tech】XMPP IOS客户端(三)

【Tech】XMPP IOS客户端(三)

上一篇实现了一个美(hen)化(chou)的聊天界面,这一篇加上发送语音和图片的功能。

其实发送语音和图片最好的办法是一端上传到服务器,另一端从服务器下载;或者用File Transfer,无奈上述第一种我不会,第二种调不通,有大神路过,望不吝指教(Orz)

我这里就是直接把语音和图片都编码为base64格式,然后放在消息里面发送过去了,其中语音是录音得到,图片则掉用相机拍摄得到。

1.发送语音

设置一个录音按钮,实现点击以下录音,再点击以下停止的功能,并且在停止后,编码为base64发送出去。录音由AVAudioRecorder实现。

按钮的action函数如下:

 1 - (IBAction)RecMethod:(id)sender { 2     if (!self.isRecording) { 3         self.isRecording = YES; 4         [self.StopOrRec setTitle:@"点击停止" forState:UIControlStateNormal]; 5         recorder = [[AVAudioRecorder alloc]initWithURL:recordFile settings:nil error:nil]; 6         [recorder prepareToRecord]; 7         [recorder record]; 8         player = nil; 9     }else{10         self.isRecording = NO;11         [self.StopOrRec setTitle:@"点击录音" forState:UIControlStateNormal];12         [recorder stop];13         recorder = nil;14         15         NSError *playerError;16         17         player = [[AVAudioPlayer alloc]initWithContentsOfURL:recordFile error:&playerError];18         if (player == nil) {19             NSLog(@"Error creating player :%@",[playerError description]);20         }21         22         /*23         NSString *docsDir;24         NSArray *dirPaths;25         26         27         dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);28         docsDir = [dirPaths objectAtIndex:0];29         NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"000005.jpg"]];30         NSError *error;31         NSURL *newURL = [NSURL fileURLWithPath:databasePath];32         [[NSFileManager defaultManager] copyItemAtURL:recordFile toURL:newURL error:&error];33         */34         35         NSData *data =http://www.mamicode.com/ [NSData dataWithContentsOfURL:recordFile];36         37         if (data) {38             NSString *base64 = [data base64EncodedString];39             [self sendAudio:base64 withName:@"test.amr"];40             41             NSMutableString *Msg = [[NSMutableString alloc]initWithString:@"base64"];42             [Msg appendFormat:@"%@",base64];43             NSMutableDictionary *dict = [NSMutableDictionary dictionary];44             [dict setObject:Msg forKey:@"msg"];45             [dict setObject:@"you" forKey:@"sender"];46             47             [messages addObject:dict];48             [self.chatTBView reloadData];49         }else{50             UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Recording Data!"51                                                                 message:@"NO DATA!"52                                                                delegate:nil53                                                       cancelButtonTitle:@"Ok"54                                                       otherButtonTitles:nil];55             [alertView show];56         }57 58         //[player play];59     }60 }61 62 63 -(void)sendAudio:(NSString *)base64String withName:(NSString *)audioName{64     NSMutableString *soundString = [[NSMutableString alloc]initWithString:@"base64"];65     [soundString appendString:base64String];66     XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.ajid];67     [message addBody:soundString];68     [[[self appDelegate] xmppStream] sendElement:message];69 }

 

这里设置一个BOOL型的isRecording变量,如果为true,说明正在录音;否则录音完毕。

录音的时候首先初始化一个recorder,然后使用这个recorder录音。

停止的时候,首先从NSURL *recordFile;这个变量得到录音文件放到data中,然后编码成base64格式发送出去,并且放到messages数组中。并且,在编码成base64字符串的时候,在字符串的开头加上base64这6个字符,表示这是一个音频文件,这样在接受的时候就知道怎么处理了。

最后我们还要实现一个效果就是点击某行的时候播放这一行对应的录音文件,再次实现tableview的代理方法didSelectRowAtIndexPath:

 1 -(IBAction)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 2     NSMutableDictionary *dict = [messages objectAtIndex:indexPath.row]; 3     NSString *message = [dict objectForKey:@"msg"]; 4     if ([message hasPrefix:@"base64"]) { 5         NSData *audioData = http://www.mamicode.com/[[message substringFromIndex:6] base64DecodedData]; 6         NSError *playerError; 7          8         if (audioData) { 9             player = [[AVAudioPlayer alloc]initWithData:audioData error:&playerError];10             [player play];11         }else{12             UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Rereading Data!"13                                                                 message:@"NO DATA!"14                                                                delegate:nil15                                                       cancelButtonTitle:@"Ok"16                                                       otherButtonTitles:nil];17             [alertView show];18         }19     }20 }

2.发送图像

首先,设计一个拍照按钮,用户点击这个按钮会调用照相机,拍照后将照片发送出去。

照相机按钮的action函数如下:

1 - (IBAction)TakePicture:(id)sender {2     UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;3     UIImagePickerController *picker = [[UIImagePickerController alloc]init];4     picker.delegate = self;5     picker.allowsEditing = YES;6     picker.sourceType = sourceType;7     [self presentViewController:picker animated:YES completion:nil];8 }

首先定义sourceType为照相机,然后用presentViewController召唤照相机。

拍照后的动作在代理函数didFinishPickingMediaWithInfo中实现,这里主要就是把拍好的照片发送出去,并且加入到messages数组中,如下:

 1 #pragma mark - 2 #pragma mark Camera View Delegate Methods 3 -(void)sendImage:(NSString *)base64String{ 4     NSMutableString *soundString = [[NSMutableString alloc]initWithString:@"image"]; 5     [soundString appendString:base64String]; 6     XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.ajid]; 7     [message addBody:soundString]; 8     [[[self appDelegate] xmppStream] sendElement:message]; 9 }10 11 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{12     UIImage *image;13     image = [info objectForKey:UIImagePickerControllerEditedImage];14     [picker dismissViewControllerAnimated:YES completion:nil];15     16     NSData *data =http://www.mamicode.com/ UIImagePNGRepresentation(image);17     if (data) {18         NSString *base64 = [data base64EncodedString];19         [self sendImage:base64];20         21         NSMutableString *Msg = [[NSMutableString alloc]initWithString:@"image"];22         [Msg appendFormat:@"%@",base64];23         NSMutableDictionary *dict = [NSMutableDictionary dictionary];24         [dict setObject:Msg forKey:@"msg"];25         [dict setObject:@"you" forKey:@"sender"];26         27         [messages addObject:dict];28         [self.chatTBView reloadData];29         30     }else{31         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ERROR!"32                                                         message:@"Can not get image data."33                                                        delegate:nil34                                               cancelButtonTitle:@"OK"35                                               otherButtonTitles:nil];36         [alert show];37     }38 }39 40 -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{41     [picker dismissViewControllerAnimated:YES completion:nil];42 }

这里的imagePickerControllerDidCancel函数表示用户在拍照后选择退出时的动作。

最终的效果如下:

技术分享

这几天的成果大概都在这里了,系统还有很多bug:

1.播放语音不能点图片,要点那一行,即上图中灰色的部分。

2.传语音和图片的时候很慢

3.键盘不会自动缩回

4.以下省略3000字。

最后上代码:github

博主新手ios小白一枚,望各路大神指教。

 

【Tech】XMPP IOS客户端(三)