源码+文档: http://download.csdn.net/detail/u012112423/9369907
1.概览
本项目需要同过PC控制Android以达到控制小车,获取视频图像的要求。主要包括TCP通信,Bluetooth通信,Camera的调用
(1) 通过监听button的pressed与released来发送控制指令
(2) 指令发送到Android手机端,继而转发给Arduino,从而控制电机正反转
(3) 通过调用Camera获取图像数据,传输到PC端,将数据转为图像显示到Image Panel中
2.关键代码分析
2.1.PC端
建立socket通信,用于接收和发送数据
public class ImageServer {
...
private static ServerSocket ss = null;
private static final int PORT = 12345, SERVERPORT = 6000;
private static Socket socket;
public ImageServer(String strip) throws IOException {
ss = new ServerSocket(SERVERPORT);
socket = new Socket(strip, PORT);
...
}
}
发送数据
public class ActionListen implements MouseListener {
OutputStream os;
InputStream is;
String ordStr;
Socket socket;
public ActionListen(Socket socket, String str) throws IOException {
ordStr = str;
this.socket = socket;
os = socket.getOutputStream();
is = socket.getInputStream();
}
@Override
public void mousePressed(MouseEvent event) {
// 发送运动方向数据
try {
byte[] buf = new byte[100];
os.write(ordStr.getBytes());
os.flush();
is.read(buf);
String str = new String(buf);
System.out.println(str);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
...
}
接收数据
class ImagePanel extends JPanel {
private ServerSocket ss;
private Image image;
private InputStream ins;
public ImagePanel(ServerSocket ss) {
this.ss = ss;
}
public void getimage() throws IOException {
Socket s = this.ss.accept();
this.ins = s.getInputStream();
this.image = ImageIO.read(ins);
}
...
}
2.2.Android端
接收PC端发送的指令class TCP_Server extends Thread {
private ServerSocket serversocket;
private Socket tcpsocket;
public TCP_Server(ServerSocket serversocket) {
this.serversocket = serversocket;
}
public void run() {
byte[] buf = null;
InputStream is = null;
OutputStream os = null;
try {
tcpsocket = serversocket.accept();
is = tcpsocket.getInputStream();
os = tcpsocket.getOutputStream();
while (true) {
buf = new byte[100];
is.read(buf);
os.write(buf);
os.flush();
String str = new String(buf);
BTconnect.sendMessage(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
获取Camera的图片流
public class StreamIt implements Camera.PreviewCallback {
private String ipname;
public StreamIt(String ipname){
this.ipname = ipname;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Size size = camera.getParameters().getPreviewSize();
try{
//调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
if(image!=null){
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outstream);
outstream.flush();
//启用线程将图像数据发送出去
Thread th = new TransPicThread(outstream,ipname);
th.start();
}
}catch(Exception ex){
Log.e("Sys","Error:"+ex.getMessage());
}
}
}
发送数据给PC端
public class TransPicThread extends Thread{
private byte byteBuffer[] = new byte[1024];
private OutputStream outsocket;
private ByteArrayOutputStream myoutputstream;
private String ipname;
public TransPicThread(ByteArrayOutputStream myoutputstream,String ipname){
this.myoutputstream = myoutputstream;
this.ipname = ipname;
try {
myoutputstream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try{
//将图像数据通过Socket发送出去
Socket tempSocket = new Socket(ipname, 6000);
outsocket = tempSocket.getOutputStream();
ByteArrayInputStream inputstream = new ByteArrayInputStream(myoutputstream.toByteArray());
int amount;
while ((amount = inputstream.read(byteBuffer)) != -1) {
outsocket.write(byteBuffer, 0, amount);
}
myoutputstream.flush();
myoutputstream.close();
tempSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
蓝牙发送和读取数据
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
@SuppressLint("NewApi")
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BTconnect.MESSAGE_READ, bytes,
-1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* @param buffer
* The bytes to write
*/
@SuppressLint("NewApi")
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BTconnect.MESSAGE_WRITE, -1, -1,
buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
蓝牙通信和tcp通信基本相似。