以TCP Socket方式实现安卓摄像头数据的传输

前言

上一篇文章中我们使用了浏览器的HTTP SERVER PUSH功能,效果还行吧,不过用户体验上要差一些,因此我在这篇文章中将介绍直接通过Socket发送图片数据,然后客户端解析数据后直接展示的功能。

效果

以TCP Socket方式实现安卓摄像头数据的传输_第1张图片
Screenshot_2016-05-17-22-52-26_com.shutup.socketc.png

Demo地址

SocketCamera

原理

其实我们上一篇文章中也是通过Socket进行数据的传输的,只是数据的解析是由浏览器完成的,我们这次改为我们自己进行解析和展示。一些技术的点还是一样的。
主要技术点:

  1. 获取原始摄像头数据
  2. 编码成合适的格式
  3. 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);    
}}

你可能感兴趣的:(以TCP Socket方式实现安卓摄像头数据的传输)