前言
上一篇文章中我们使用了浏览器的HTTP SERVER PUSH功能,效果还行吧,不过用户体验上要差一些,因此我在这篇文章中将介绍直接通过Socket发送图片数据,然后客户端解析数据后直接展示的功能。
效果
Demo地址
原理
其实我们上一篇文章中也是通过Socket进行数据的传输的,只是数据的解析是由浏览器完成的,我们这次改为我们自己进行解析和展示。一些技术的点还是一样的。
主要技术点:
- 获取原始摄像头数据
- 编码成合适的格式
- socket发送出去
说明
我们这里的发送和接收仍然是在单独的线程中实现,通过handler和主线程进行交互。
服务端的发送逻辑:先发送数据的长度,占4个字节,接着发送数据的字节数组。
class ServerWriter extends Thread {
@Override
public void run() {
super.run();
try {
//listen on 8888
mServerSocket = new ServerSocket(8888);
mSocket = mServerSocket.accept();
mOutputStream = mSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
while (isRun) {
if (isOk) {
try {
//first write the data length to the outputStream ,it need a int size 4
mOutputStream.write(ByteBuffer.allocate(4).putInt(baos.size()).array());
//then write the data to the outputStream
mOutputStream.write(baos.toByteArray());
mOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
//if have any exception,close the thread
isRun = false;
}
isOk = false;
}
}
}
}
客户端的接收逻辑:先读取4个字节,解析出数据的长度,然后通过循环读出所有的数据,循环的逻辑是这样的,如果剩余的待读取字节小于了我们缓冲区的大小,那么直接读取对应的大小,否则继续按照缓冲区大小进行读取。
while (isRun) {
byte[] sizeArray = new byte[4];
try {
mInputStream.read(sizeArray);
} catch (IOException e) {
e.printStackTrace();
}
int picLength = ByteBuffer.wrap(sizeArray).asIntBuffer().get();
if (picLength == 0){
isRun = false;
}
Log.d("ClientReader", "picLength:" + picLength);
byte[] b = new byte[picLength];
try {
int totalLen = 0;
int bufferSize = 4 * 1024;
//when the read totalLen is less than the picLength
while (totalLen < picLength) {
int len = 0;
//if the left data is less than bufferSize,read them all ,
//else read them by bufferSize
if (bufferSize >= picLength - totalLen) {
len = mInputStream.read(b, totalLen, picLength - totalLen);
} else {
len = mInputStream.read(b, totalLen, bufferSize);
}
totalLen += len;
}
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream inputStream = new ByteArrayInputStream(b);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Message message = mHandler.obtainMessage();
message.what = 1;
if (bitmap != null) {
message.obj = bitmap;
mHandler.sendMessage(message);
}}