标签:
首先声明,这是从官方给出的demo修改而来的。
1.三个用到的Thread的意义:
(1)AcceptThread
服务器端,起监听作用。(accept函数)
(2)ConnectThread
This thread runs while attempting to make an outgoing connection with a device.(正在试图连接)
(3)ConnectedThread
This thread runs during a connection with a remote device. It handles all incoming and outgoing transmissions.(已经连接,准备进行数据交换)
2.流程
BluetoothChat加载的同时启动BluetoothChatService。
(1)点击右上角的“瞄准镜”图标,调用ensureDiscoverable,使自己可被周围的蓝牙检测到
(2)点击右上角的“搜索”图标,进入DeviceListActivity。它其实是一个对话框,显示了已经配对的蓝牙和一个button。点击button调用doDiscovery搜索周围的蓝牙设备,同时使自己不可见。
点击蓝牙列表中的任意一项,响应OnItemClickListener,将需要的信息通过intent回传给BluetoothChat。同时,DeviceListActivity注册一个BroadcastReceiver检测是否四周有新打开的BluetoothDevice
(3)BluetoothChat响应onActivityResult,调用connectDevice。获取传过来的intent数据,马上再调用BluetoothChatService的connect方法。
在这个方法里面取消正在试图连接或者已经连接的线程。然后重启一个试图连接的线程(ConnectThread),并设置状态位,在BluetoothChat的mHandler处获得响应
4.ConnectThread里面mmSocket.connect();表示已连接。如果失败,调用connectionFailed然后return。如果成功,调用connected(mmSocket, mmDevice, mSocketType)。
connectionFailed函数把“失败”的消息传给handler交给BluetoothChat来显示,然后调用BluetoothChatService.this.start()取消正在试图连接或者已经连接的线程,然后重启一个AcceptThread线程继续监听(accept)。
connected(mmSocket, mmDevice, mSocketType)取消所有线程,开启ConnectedThread进行数据传输,同时通过handler向BluetoothChat发送“连接成功”消息。
5.ConnectedThread里面就是io和数据传输。传输过程中可能会有蓝牙掉线。调用connectionLost,重启BluetoothChatService
(1)通过点击edittext之外的部分使软键盘隐藏
setupUI(findViewById(R.id.root));//定义main.xml里面最大的LinearLayout的id=root
函数功能:遍历所有控件,包括子控件,只要点击的view不是Edittext就隐藏软键盘
(2)表情传输
initFaceView();
利用反射机制实现“根据文件名加载图片“
再将图片信息以二进制数据的形式传给另一端,另一端得到数据后用正则表达式来判断消息内是否有表情
SpannableString spannableString = ExpressionUtil.getExpressionString(context, str, zhengze);
(3)语音传输
数据传输部分,官方给的方法对于语音不适合。
byte[] buffer = new byte[1024];
bytes = mmInStream.read(buffer);
官方给的1024缓存对于字符而言够了,但是对于语音不够。
蓝牙传输速度有限,一个几秒的语音就要分好几次,所以要全部读完再来判断
所以要修改ConnectedThread中的run方法。同时记住,获取完所有数据以后不能结束run方法。因为还有数据的传输
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes = 0;
String source = "";
// 获得所有数据
// 官方给的方法对于语音不适合。蓝牙传输速度有限,一个几秒的语音就要分好几次
// 所以要全部读完再来判断
while (true) {
try {
bytes = mmInStream.read(buffer);
String temp = new String(buffer, 0, bytes);
source += temp;
Log.i("bytes", bytes + "");
// 这个989是通过后台log查看到的,具体为啥是这个值我不知道
if (bytes < 989) {
// voice
if (source.contains("Recorder")) {
// 构造Recorder
int end = source.lastIndexOf("]");
int start = source.indexOf("[") + 1;
String[] sub = source.substring(start, end).split(
", ");
int tempInteger = sub[0].indexOf("=") + 1;
String content = sub[0].substring(tempInteger,
sub[0].length());
float audioLength = Float.parseFloat(sub[1]
.split("=")[1]);
String filePath = sub[2].split("=")[1];
Recorder recorder = new Recorder(content,
audioLength, filePath,
BluetoothChat.VOICE_READ);
mHandler.obtainMessage(BluetoothChat.VOICE_READ,
bytes, -1, recorder).sendToTarget();
} else {
// message
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ,
bytes, -1, buffer).sendToTarget();
}
source = "";
}
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
return;
}
}
}
注意,上面的代码有bug。语音传输以后声音不对,因为没有对语音进行编码解码。只是用了二进制数据。string类型通过二进制编码解码还可以还原,语音不行
附上源码:http://download.csdn.net/detail/lxj1137800599/9514013
标签:
原文地址:http://blog.csdn.net/lxj1137800599/article/details/51350640