您的位置:首页 > 编程语言

iPhone蓝牙编程之实现语音聊天

2012-11-04 10:36 369 查看
感谢原创人。致敬!!

IT168技术】在我之前的iPhone文章中,我们已经介绍过使用GameKit框架在两个设备之间通过蓝牙通信,在这篇文章中,我将为大家介绍GameKit框架另一个很酷的功能 — 语音聊天。

  Gamekit中的语音聊天服务允许两台iPhone/iPod Touch之间建立语音聊天,语音聊天要么通过互联网,要么通过蓝牙实现,你将在本文中看到如何通过蓝牙通信信道实现语音聊天。

  创建项目

  首先使用Xcode创建一个新的基于视图的iPhone应用程序,取名为Bluetooth,在Xcode的框架组上点击右键,选择“增加”,从现有框架中选择一个增加到项目上,这里选择GameKit.framework,同时再增加一个AVFoundation框架。

  在BluetoothViewController.h文件中,增加下面的代码:

1 #import
<UIKit/UIKit.h>

2 #import
<GameKit/GameKit.h>

3 #import
<AVFoundation/AVFoundation.h>

4 @interface BluetoothViewController : UIViewController

5    <GKVoiceChatClient>
{

6

7    GKSession
*currentSession;

8    

9    IBOutlet
UIButton *connect;

10    IBOutlet
UIButton *disconnect;

11 }

12 @property (nonatomic, retain) GKSession
*currentSession;

13 @property (nonatomic, retain) UIButton
*connect;

14 @property (nonatomic, retain) UIButton
*disconnect;

15

16 -(IBAction) btnMute:(id) sender;

17 -(IBAction) btnUnmute:(id) sender;

18 -(IBAction) btnConnect:(id) sender;

19 -(IBAction) btnDisconnect:(id) sender;

20 @end

21

  拖动一个wav文件(如无特殊说明,指beep.wav)到Xcode的Resources文件夹上。

  双击BluetoothViewController.xib文件在Interface Builder编辑它,使用三个圆形按钮填充到视图窗口中,如图1所示。



  图 1 使用三个圆形按钮填充视图窗口
  在BluetoothViewController.xib窗口中,执行以下连接:

  按住CTRL键,点击文件所有者项目,将其拖放到Connect按钮上,选择连接;

  按住CTRL键,点击文件所有者项目,将其拖放到Disconnect按钮上,选择断开连接;

  按住CTRL键,点击Connect按钮,将其拖放到文件所有者项目上,选择btnConnect;

  按住CTRL键,点击Disconnect按钮,将其拖放到文件所有者项目上,选择btnDisconnect;

  在Mute按钮上点击右键,将Touch Down事件连接到文件所有者项目上,选择btnMute;

  在Mute按钮上点击右键,将Touch Up Inside事件连接到文件所有者项目上,选择btnUnmute;

  为了验证所有连接是否正确,在文件所有者项目上点击右键,查看其连接,如图2所示。



  图 2 验证出口和行为的连接
  在BluetoothViewController.m文件中,增加下面的代码:

1 #import
"BluetoothViewController.h"

2 #import
<GameKit/GameKit.h>

3 #import
<AVFoundation/AVFoundation.h>

4

5 @implementation BluetoothViewController

6 @synthesize currentSession;

7 @synthesize connect;

8 @synthesize disconnect;

9

10 GKPeerPickerController
*picker;

11 NSString
*recorderFilePath;

12

13 AVAudioPlayer
*audioPlayer;

14

15 - (void)viewDidLoad {

16

17 [connect setHidden:NO];

18 [disconnect setHidden:YES];

19

20 [super viewDidLoad];

21 }

22

23 - (IBAction) btnConnect:(id) sender {

24

25 //---选择一个附近的蓝牙设备---

26 picker
= [[GKPeerPickerController alloc] init];

27 picker.delegate
= self;

28 picker.connectionTypesMask
= GKPeerPickerConnectionTypeNearby;

29

30 [connect setHidden:YES];

31 [disconnect setHidden:NO];

32

33 [picker show];

34

35 }

36

37 -(IBAction) btnDisconnect:(id) sender {

38

39 //---从其它设备断开连接---

40 [self.currentSession disconnectFromAllPeers];

41 [self.currentSession release];

42 currentSession
= nil;

43

44 [connect setHidden:NO];

45 [disconnect setHidden:YES];

46

47 }

48

49 - (void)peerPickerController:(GKPeerPickerController
*)picker

50 didConnectPeer:(NSString
*)peerID

51 toSession: (GKSession
*) session {

52

53 self.currentSession
= session;

54 session.delegate
= self;

55 [session setDataReceiveHandler: self withContext:nil];

56 picker.delegate
= nil;

57 [picker dismiss];

58 [picker autorelease];

59

60 }

61

62 - (void)peerPickerControllerDidCancel:(GKPeerPickerController
*)picker {

63

64 picker.delegate
= nil;

65 [picker autorelease];

66

67 [connect setHidden:NO];

68 [disconnect setHidden:YES];

69

70 }

71

72 -(IBAction) btnMute:(id) sender {

73

74 //---静音语音聊天---

75 [GKVoiceChatService defaultVoiceChatService].microphoneMuted
= YES;

76

77 }

78

79 -(IBAction) btnUnmute:(id) sender {

80

81 //---取消静音---

82 [GKVoiceChatService defaultVoiceChatService].microphoneMuted
= NO;

83

84 }

85

86 //---返回一个表示本地用户的唯一ID
---

87 -(NSString
*) participantID

88 {

89 return currentSession.peerID;

90 }

91

92 -(void) voiceChatService:(GKVoiceChatService
*) voiceChatService

93 sendData:(NSData
*) data

94 toParticipantID:(NSString
*)participantID {

95

96 [currentSession sendData:data toPeers:

97 [NSArray arrayWithObject:participantID]

98 withDataMode:GKSendDataReliable
error:nil];

99

100 }

101

102 - (void)session:(GKSession
*)session

103 peer:(NSString
*)peerID

104 didChangeState:(GKPeerConnectionState)state {

105

106 switch (state)

107 {

108 case GKPeerStateConnected:

109 {

110 //---播放一个音频文件---

111 NSString
*soundFilePath
= [[NSBundle mainBundle]

112 pathForResource:@"beep" ofType:@"wav"];

113

114 NSURL
*fileURL
= [[NSURL alloc]

115 initFileURLWithPath: soundFilePath];

116

117 AVAudioPlayer
*audioPlayer
=

118 [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL

119
error:nil];

120

121 [fileURL release];

122 [audioPlayer play];

123

124 NSError
*error;

125 AVAudioSession
*audioSession
=

126 [AVAudioSession sharedInstance];

127

128 if (![audioSession

129 setCategory:AVAudioSessionCategoryPlayAndRecord

130 error:&error])
{

131 NSLog(@"Error setting the AVAudioSessionCategoryPlayAndRecord category: %@",

132 [error localizedDescription]);

133 }

134

135 if (![audioSession setActive: YES
error:
&error]) {

136 NSLog(@"Error activating audioSession: %@",

137 [error description]);

138 }

139

140 [GKVoiceChatService defaultVoiceChatService].client
= self;

141

142 //---初始化语音聊天---

143 if (![[GKVoiceChatService defaultVoiceChatService]

144 startVoiceChatWithParticipantID:peerID
error:&error]) {

145 NSLog(@"Error starting startVoiceChatWithParticipantID: %@",

146 [error userInfo]);

147 }

148 } break;

149

150 case GKPeerStateDisconnected:

151 {

152 [[GKVoiceChatService defaultVoiceChatService]

153 stopVoiceChatWithParticipantID:peerID];

154

155 [self.currentSession release];

156 currentSession
= nil;

157

158 [connect setHidden:NO];

159 [disconnect setHidden:YES];

160

161 } break;

162 }

163 }

164

165 - (void) receiveData:(NSData
*)data

166 fromPeer:(NSString
*)peer

167 inSession:(GKSession
*)session

168 context:(void
*)context {

169

170 //---初始化完成后开始语音聊天---

171 [[GKVoiceChatService defaultVoiceChatService]

172 receivedData:data fromParticipantID:peer];

173

174 }

175

176 - (void)dealloc {

177

178 if (currentSession) [currentSession release];

179 [connect release];

180 [disconnect release];

181

182 [super dealloc];

183 }

184 @end

185

  理解语音聊天是如何工作的

  当两个蓝牙设备连接时,首先播放beep.wav文件发出嘟嘟声,然后启动语音会话(通过session:peer:didChangeState:方法实现)。

1 NSString
*soundFilePath
= [[NSBundle mainBundle]

2 pathForResource:@"beep" ofType:@"wav"];

3

4 NSURL
*fileURL
= [[NSURL alloc]

5 initFileURLWithPath: soundFilePath];

6

7 AVAudioPlayer
*audioPlayer
=

8 [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL

9
error:nil];

10

11 [fileURL release];

12 [audioPlayer play];

13

14 NSError
*error;

15 AVAudioSession
*audioSession
=

16 [AVAudioSession sharedInstance];

17

18 if (![audioSession

19 setCategory:AVAudioSessionCategoryPlayAndRecord

20 error:&error])
{

21 NSLog(@"Error setting the AVAudioSessionCategoryPlayAndRecord category: %@",

22 [error localizedDescription]);

23 }

24

25 if (![audioSession setActive: YES
error:
&error]) {

26 NSLog(@"Error activating audioSession: %@",

27 [error description]);

28 }

29

30 [GKVoiceChatService defaultVoiceChatService].client
= self;

31

  提示:有趣的是,如果你不启动音频播放器,语音聊天不能正常工作。

  然后检索GKVoiceChatService类的单一实例,调用它的startVoiceChatWithParticipantID:error:方法启动语音聊天。

1 if (![[GKVoiceChatService defaultVoiceChatService]

2 startVoiceChatWithParticipantID:peerID
error:&error]) {

3 NSLog(@"Error starting startVoiceChatWithParticipantID: %@",

4 [error userInfo]);

5 }

6

  调用startVoiceChatWithParticipantID:error:方法将会请求voiceChatService:sendData:toParticipantID:方法,它将会使用当前的蓝牙会话发送配置数据到其它设备。

1 -(void) voiceChatService:(GKVoiceChatService
*) voiceChatService

2 sendData:(NSData
*) data

3 toParticipantID:(NSString
*)participantID {

4

5 [currentSession sendData:data toPeers:

6 [NSArray arrayWithObject:participantID]

7 withDataMode:GKSendDataReliable
error:nil];

8

9 }

10

  其它连接的设备接收到发来的配置数据后,通过调用receivedData:fromParticipantID:方法启动语音聊天服务。

  GKVoiceChatService使用两个设备之间交互的配置信息创建它自己的连接传输语音数据,还可以将microphoneMuted属性的值设为YES使麦克风静音。

1 [GKVoiceChatService defaultVoiceChatService].microphoneMuted
= YES;

  测试应用程序

  在开始测试之前,先要把应用程序两台iPhone或iPod Touch上,对于iPod Touch,你需要使用一个外置麦克风,因为它默认是不带有麦克风的,一个好选择是Griffin iTalk Pro,如图3所示,它是iPod Touch麦克风及其零配件插入的基座,另外也支持苹果头戴式耳机及其配件。



  应用程序部署到设备上后,启动应用程序,按下Connect按钮使用蓝牙相互连接,当两个设备连接好后,就可以开始聊天了,如果要临时静音,按下Mute按钮一直不放即可,放开Mute按钮后,声音就又恢复了。

  在这篇文章中,你看到了如何使用Gamekit框架提供的GKVoiceChatService类在两个设备之间无缝地建立语音通信,关于两个设备之间的语音是如何传输的暂时没有必要知道,所有需要了解的就是要知道调用什么方法初始化语音聊天,另外你还要知道,语音聊天不仅可以通过蓝牙通信信道实现,在其它任何通信信道上都可以实现,实际上,如果使用TCP/IP连接两台设备,也可以实现语音聊天,在今后的文章中,我将会涉及。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: