PC客户端与 Android服务端的 Socket同步通信(USB)


PC 客户端与 Android 服务端的 Socket 同步通信(USB) 需求: 1.一个 android 端的 service 后台运行的程序,作为 socket 的服务器端;用于接收 Pc client 端发来的命令,来处理数据后,把结果发给 PC client 2.PC 端程序,作为 socket 的客户端,用于给 android 手机端发操作命令 难点分析: 1.手机一定要有 adb 模式,即插上 USB 线时马上提示的对话框选 adb。好多对手机的 操作都可以用 adb 直接作 不过,我发现 LG GW880 就没有,要去下载个 2.android 默认手机端的 IP 为“127.0.0.1” 3.要想联通 PC 与 android 手机的 sokcet,一定要用 adb forward 来作下端口转发才能连 上 socket. view plaincopy to clipboardprint? Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); Thread.sleep(3000); Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); Thread.sleep(3000); 4.android 端的 service 程序 Install 到手机上容易,但是还要有方法来从 PC 的 client 端来启动手机上的 service ,这个办法可以通过 PC 端 adb 命令来发一个 Broastcast ,手机 端再写个接收 BroastcastReceive 来接收这个 Broastcast,在这个 BroastcastReceive 来启动 service pc 端命令: view plaincopy to clipboardprint? Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStart"); Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStart"); android 端的代码:ServiceBroadcastReceiver.java view plaincopy to clipboardprint? package com.otheri.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class ServiceBroadcastReceiver extends BroadcastReceiver { private static String START_ACTION = "NotifyServiceStart"; private static String STOP_ACTION = "NotifyServiceStop"; @Override public void onReceive(Context context, Intent intent) { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive"); String action = intent.getAction(); if (START_ACTION.equalsIgnoreCase(action)) { context.startService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive start end"); } else if (STOP_ACTION.equalsIgnoreCase(action)) { context.stopService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive stop end"); } } } package com.otheri.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class ServiceBroadcastReceiver extends BroadcastReceiver { private static String START_ACTION = "NotifyServiceStart"; private static String STOP_ACTION = "NotifyServiceStop"; @Override public void onReceive(Context context, Intent intent) { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive"); String action = intent.getAction(); if (START_ACTION.equalsIgnoreCase(action)) { context.startService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive start end"); } else if (STOP_ACTION.equalsIgnoreCase(action)) { context.stopService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive stop end"); } } } 5.由于是 USB 连接,所以 socket 就可以设计为一但连接就一直联通,即在 new socket 和 开完 out,in 流后,就用个 while(true){}来循环 PC 端和 android 端的读和写 android 的代码: view plaincopy to clipboardprint? public void run() { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "a client has connected to server!"); BufferedOutputStream out; BufferedInputStream in; try { /* PC 端发来的数据 msg */ String currCMD = ""; out = new BufferedOutputStream(client.getOutputStream()); in = new BufferedInputStream(client.getInputStream()); // testSocket();// 测试 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) { try { if (!client.isConnected()) { break; } /* 接收 PC 发来的数据 */ Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "will read......"); /* 读操作命令 */ currCMD = readCMDFromSocket(in); Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "**currCMD ==== " + currCMD); /* 根据命令分别处理数据 */ if (currCMD.equals("1")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("2")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("3")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("4")) { /* 准备接收文件数据 */ try { out.write("service receive OK".getBytes()); out.flush(); } catch (IOException e) { e.printStackTrace(); } /* 接收文件数据,4 字节文件长度,4 字节文件格式,其后是文 件数据 */ byte[] filelength = new byte[4]; byte[] fileformat = new byte[4]; byte[] filebytes = null; /* 从 socket 流中读取完整文件数据 */ filebytes = receiveFileFromSocket(in, out, filelength, fileformat); // Log.v(Service139.TAG, "receive data =" + new // String(filebytes)); try { /* 生成文件 */ File file = FileHelper.newFile("R0013340.JPG"); FileHelper.writeFile(file, filebytes, 0, filebytes.length); } catch (IOException e) { e.printStackTrace(); } } else if (currCMD.equals("exit")) { } } catch (Exception e) { // try { // out.write("error".getBytes("utf-8")); // out.flush(); // } catch (IOException e1) { // e1.printStackTrace(); // } Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error111111"); } } out.close(); in.close(); } catch (Exception e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error222222"); e.printStackTrace(); } finally { try { if (client != null) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "client.close()"); client.close(); } } catch (IOException e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error333333"); e.printStackTrace(); } } public void run() { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "a client has connected to server!"); BufferedOutputStream out; BufferedInputStream in; try { /* PC 端发来的数据 msg */ String currCMD = ""; out = new BufferedOutputStream(client.getOutputStream()); in = new BufferedInputStream(client.getInputStream()); // testSocket();// 测试 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) { try { if (!client.isConnected()) { break; } /* 接收 PC 发来的数据 */ Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "will read......"); /* 读操作命令 */ currCMD = readCMDFromSocket(in); Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "**currCMD ==== " + currCMD); /* 根据命令分别处理数据 */ if (currCMD.equals("1")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("2")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("3")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("4")) { /* 准备接收文件数据 */ try { out.write("service receive OK".getBytes()); out.flush(); } catch (IOException e) { e.printStackTrace(); } /* 接收文件数据,4 字节文件长度,4 字节文件格式,其后是文 件数据 */ byte[] filelength = new byte[4]; byte[] fileformat = new byte[4]; byte[] filebytes = null; /* 从 socket 流中读取完整文件数据 */ filebytes = receiveFileFromSocket(in, out, filelength, fileformat); // Log.v(Service139.TAG, "receive data =" + new // String(filebytes)); try { /* 生成文件 */ File file = FileHelper.newFile("R0013340.JPG"); FileHelper.writeFile(file, filebytes, 0, filebytes.length); } catch (IOException e) { e.printStackTrace(); } } else if (currCMD.equals("exit")) { } } catch (Exception e) { // try { // out.write("error".getBytes("utf-8")); // out.flush(); // } catch (IOException e1) { // e1.printStackTrace(); // } Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error111111"); } } out.close(); in.close(); } catch (Exception e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error222222"); e.printStackTrace(); } finally { try { if (client != null) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "client.close()"); client.close(); } } catch (IOException e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error333333"); e.printStackTrace(); } } 6.如果是在 PC 端和 android 端的读写操作来 while(true){}循环,这样 socket 流的结尾不好 判断,不能用“-1”来判断,因为“-1”是只有在 socket 关闭时才作为判断结尾。 7.socket 在 out.write(bytes);时,要是数据太大时,超过 socket 的缓存,socket 自动分包发 送,所以对方就一定要用循环来多次读。最好的办法就是服务器和客户端协议好,比如发文 件时,先写过来一个要发送的文件的大小,然后再发送文件;对方用这个大小,来循环读取 数据。 android 端接收数据的代码: view plaincopy to clipboardprint? /** * 功能:从 socket 流中读取完整文件数据 * * InputStream in:socket 输入流 * * byte[] filelength: 流的前 4 个字节存储要转送的文件的字节数 * * byte[] fileformat:流的前 5-8 字节存储要转送的文件的格式(如.apk) * * */ public static byte[] receiveFileFromSocket(InputStream in, OutputStream out, byte[] filelength, byte[] fileformat) { byte[] filebytes = null;// 文件数据 try { int filelen = MyUtil.bytesToInt(filelength);// 文件长度从 4 字节 byte[]转成 Int String strtmp = "read file length ok:" + filelen; out.write(strtmp.getBytes("utf-8")); out.flush(); filebytes = new byte[filelen]; int pos = 0; int rcvLen = 0; while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) { pos += rcvLen; } Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "read file OK:file size=" + filebytes.length); out.write("read file ok".getBytes("utf-8")); out.flush(); } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "receiveFileFromSocket error"); e.printStackTrace(); } return filebytes; } /** * 功能:从 socket 流中读取完整文件数据 * * InputStream in:socket 输入流 * * byte[] filelength: 流的前 4 个字节存储要转送的文件的字节数 * * byte[] fileformat:流的前 5-8 字节存储要转送的文件的格式(如.apk) * * */ public static byte[] receiveFileFromSocket(InputStream in, OutputStream out, byte[] filelength, byte[] fileformat) { byte[] filebytes = null;// 文件数据 try { int filelen = MyUtil.bytesToInt(filelength);// 文件长度从 4 字节 byte[]转成 Int String strtmp = "read file length ok:" + filelen; out.write(strtmp.getBytes("utf-8")); out.flush(); filebytes = new byte[filelen]; int pos = 0; int rcvLen = 0; while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) { pos += rcvLen; } Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "read file OK:file size=" + filebytes.length); out.write("read file ok".getBytes("utf-8")); out.flush(); } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "receiveFileFromSocket error"); e.printStackTrace(); } return filebytes; } 8.socket 的最重要的机制就是读写采用的是阻塞的方式,如果客户端作为命令发起者,服 务器端作为接收者的话,只有当客户端 client 用 out.writer()写到输出流里后,即流中有数据 service 的 read 才会执行,不然就会一直停在 read()那里等数据。 9.还要让服务器端可以同时连接多个 client,即服务器端用 new thread()来作数据读取操作。 源码: 客户端(pc 端): testPcClient.java view plaincopy to clipboardprint? import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; public class testPcClient { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { try { Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStop"); Thread.sleep(3000); Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); Thread.sleep(3000); Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStart"); Thread.sleep(3000); } catch (IOException e3) { e3.printStackTrace(); } Socket socket = null; try { InetAddress serverAddr = null; serverAddr = InetAddress.getByName("127.0.0.1"); System.out.println("TCP 1111" + "C: Connecting..."); socket = new Socket(serverAddr, 12580); String str = "hi,wufenglong"; System.out.println("TCP 221122" + "C:RECEIVE"); BufferedOutputStream out = new BufferedOutputStream(socket .getOutputStream()); BufferedInputStream in = new BufferedInputStream(socket .getInputStream()); BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); boolean flag = true; while (flag) { System.out.print("请输入 1~6 的数字,退出输入 exit:"); String strWord = br.readLine();// 从控制台输入 1~6 if (strWord.equals("1")) { out.write("1".getBytes()); out.flush(); System.out.println("1 finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); System.out .println("====================================== ======="); } else if (strWord.equals("2")) { out.write("2".getBytes()); out.flush(); System.out.println("2 finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); System.out .println("====================================== ======="); } else if (strWord.equals("3")) { out.write("3".getBytes()); out.flush(); System.out.println("3 finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); System.out .println("====================================== ======="); } else if (strWord.equals("4")) { /* 发送命令 */ out.write("4".getBytes()); out.flush(); System.out.println("send file finish sending the CMD:"); /* 服务器反馈:准备接收 */ String strFormsocket = readFromSocket(in); System.out .println("service ready receice data:UPDATE_CONTACTS:" + strFormsocket); byte[] filebytes = FileHelper.readFile("R0013340.JPG"); System.out.println("file size=" + filebytes.length); /* 将整数转成 4 字节 byte 数组 */ byte[] filelength = new byte[4]; filelength = tools.intToByte(filebytes.length); /* 将.apk 字符串转成 4 字节 byte 数组 */ byte[] fileformat = null; fileformat = ".apk".getBytes(); System.out .println("fileformat length=" + fileformat.length); /* 字节流中前 4 字节为文件长度,4 字节文件格式,以后是文件流 */ /* 注意如果 write 里的 byte[]超过 socket 的缓存,系统自动分包写过 去,所以对方要循环写完 */ out.write(filelength); out.flush(); String strok1 = readFromSocket(in); System.out.println("service receive filelength :" + strok1); // out.write(fileformat); // out.flush(); // String strok2 = readFromSocket(in); // System.out.println("service receive fileformat :" + // strok2); System.out.println("write data to android"); out.write(filebytes); out.flush(); System.out.println("*********"); /* 服务器反馈:接收成功 */ String strread = readFromSocket(in); System.out.println(" send data success:" + strread); System.out .println("====================================== ======="); } else if (strWord.equalsIgnoreCase("EXIT")) { out.write("EXIT".getBytes()); out.flush(); System.out.println("EXIT finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); flag = false; System.out .println("====================================== ======="); } } } catch (UnknownHostException e1) { System.out.println("TCP 331133" + "ERROR:" + e1.toString()); } catch (Exception e2) { System.out.println("TCP 441144" + "ERROR:" + e2.toString()); } finally { try { if (socket != null) { socket.close(); System.out.println("socket.close()"); } } catch (IOException e) { System.out.println("TCP 5555" + "ERROR:" + e.toString()); } } } /* 从 InputStream 流中读数据 */ public static String readFromSocket(InputStream in) { int MAX_BUFFER_BYTES = 4000; String msg = ""; byte[] tempbuffer = new byte[MAX_BUFFER_BYTES]; try { int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length); msg = new String(tempbuffer, 0, numReadedBytes, "utf-8"); tempbuffer = null; } catch (Exception e) { e.printStackTrace(); } // Log.v(Service139.TAG, "msg=" + msg); return msg; } } import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; public class testPcClient { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { try { Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStop"); Thread.sleep(3000); Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); Thread.sleep(3000); Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStart"); Thread.sleep(3000); } catch (IOException e3) { e3.printStackTrace(); } Socket socket = null; try { InetAddress serverAddr = null; serverAddr = InetAddress.getByName("127.0.0.1"); System.out.println("TCP 1111" + "C: Connecting..."); socket = new Socket(serverAddr, 12580); String str = "hi,wufenglong"; System.out.println("TCP 221122" + "C:RECEIVE"); BufferedOutputStream out = new BufferedOutputStream(socket .getOutputStream()); BufferedInputStream in = new BufferedInputStream(socket .getInputStream()); BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); boolean flag = true; while (flag) { System.out.print("请输入 1~6 的数字,退出输入 exit:"); String strWord = br.readLine();// 从控制台输入 1~6 if (strWord.equals("1")) { out.write("1".getBytes()); out.flush(); System.out.println("1 finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); System.out .println("============================================="); } else if (strWord.equals("2")) { out.write("2".getBytes()); out.flush(); System.out.println("2 finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); System.out .println("============================================="); } else if (strWord.equals("3")) { out.write("3".getBytes()); out.flush(); System.out.println("3 finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); System.out .println("============================================="); } else if (strWord.equals("4")) { /* 发送命令 */ out.write("4".getBytes()); out.flush(); System.out.println("send file finish sending the CMD:"); /* 服务器反馈:准备接收 */ String strFormsocket = readFromSocket(in); System.out .println("service ready receice data:UPDATE_CONTACTS:" + strFormsocket); byte[] filebytes = FileHelper.readFile("R0013340.JPG"); System.out.println("file size=" + filebytes.length); /* 将整数转成 4 字节 byte 数组 */ byte[] filelength = new byte[4]; filelength = tools.intToByte(filebytes.length); /* 将.apk 字符串转成 4 字节 byte 数组 */ byte[] fileformat = null; fileformat = ".apk".getBytes(); System.out .println("fileformat length=" + fileformat.length); /* 字节流中前 4 字节为文件长度,4 字节文件格式,以后是文件流 */ /* 注意如果 write 里的 byte[]超过 socket 的缓存,系统自动分包写过 去,所以对方要循环写完 */ out.write(filelength); out.flush(); String strok1 = readFromSocket(in); System.out.println("service receive filelength :" + strok1); // out.write(fileformat); // out.flush(); // String strok2 = readFromSocket(in); // System.out.println("service receive fileformat :" + // strok2); System.out.println("write data to android"); out.write(filebytes); out.flush(); System.out.println("*********"); /* 服务器反馈:接收成功 */ String strread = readFromSocket(in); System.out.println(" send data success:" + strread); System.out .println("============================================="); } else if (strWord.equalsIgnoreCase("EXIT")) { out.write("EXIT".getBytes()); out.flush(); System.out.println("EXIT finish sending the data"); String strFormsocket = readFromSocket(in); System.out.println("the data sent by server is:\r\n" + strFormsocket); flag = false; System.out .println("============================================="); } } } catch (UnknownHostException e1) { System.out.println("TCP 331133" + "ERROR:" + e1.toString()); } catch (Exception e2) { System.out.println("TCP 441144" + "ERROR:" + e2.toString()); } finally { try { if (socket != null) { socket.close(); System.out.println("socket.close()"); } } catch (IOException e) { System.out.println("TCP 5555" + "ERROR:" + e.toString()); } } } /* 从 InputStream 流中读数据 */ public static String readFromSocket(InputStream in) { int MAX_BUFFER_BYTES = 4000; String msg = ""; byte[] tempbuffer = new byte[MAX_BUFFER_BYTES]; try { int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length); msg = new String(tempbuffer, 0, numReadedBytes, "utf-8"); tempbuffer = null; } catch (Exception e) { e.printStackTrace(); } // Log.v(Service139.TAG, "msg=" + msg); return msg; } } android 服务器端: 主类 androidService.java view plaincopy to clipboardprint? package com.otheri.service; import java.io.File; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.util.Log; /** * 设置:android 手机 * * * */ public class androidService extends Service { public static final String TAG = "TAG"; public static Boolean mainThreadFlag = true; public static Boolean ioThreadFlag = true; ServerSocket serverSocket = null; final int SERVER_PORT = 10086; File testFile; private sysBroadcastReceiver sysBR; @Override public void onCreate() { super.onCreate(); Log.v(TAG, Thread.currentThread().getName() + "---->" + " onCreate"); /* 创建内部类 sysBroadcastReceiver 并注册 registerReceiver */ sysRegisterReceiver(); new Thread() { public void run() { doListen(); }; }.start(); } private void doListen() { Log.d(TAG, Thread.currentThread().getName() + "---->" + " doListen() START"); serverSocket = null; try { Log.d(TAG, Thread.currentThread().getName() + "---->" + " doListen() new serverSocket"); serverSocket = new ServerSocket(SERVER_PORT); boolean mainThreadFlag = true; while (mainThreadFlag) { Log.d(TAG, Thread.currentThread().getName() + "---->" + " doListen() listen"); Socket client = serverSocket.accept(); new Thread(new ThreadReadWriterIOSocket(this, client)).start(); } } catch (IOException e1) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "new serverSocket error"); e1.printStackTrace(); } } /* 创建内部类 sysBroadcastReceiver 并注册 registerReceiver */ private void sysRegisterReceiver() { Log.v(TAG, Thread.currentThread().getName() + "---->" + "sysRegisterReceiver"); sysBR = new sysBroadcastReceiver(); /* 注册 BroadcastReceiver */ IntentFilter filter1 = new IntentFilter(); /* 新的应用程序被安装到了设备上的广播 */ filter1.addAction("android.intent.action.PACKAGE_ADDED"); filter1.addDataScheme("package"); filter1.addAction("android.intent.action.PACKAGE_REMOVED"); filter1.addDataScheme("package"); registerReceiver(sysBR, filter1); } /* 内部类:BroadcastReceiver 用于接收系统事件 */ private class sysBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equalsIgnoreCase("android.intent.action.PACKAGE_ADDED")) { // ReadInstalledAPP(); } else if (action .equalsIgnoreCase("android.intent.action.PACKAGE_REMOVED")) { // ReadInstalledAPP(); } Log.v(TAG, Thread.currentThread().getName() + "---->" + "sysBroadcastReceiver onReceive"); } } @Override public void onDestroy() { super.onDestroy(); // 关闭线程 mainThreadFlag = false; ioThreadFlag = false; // 关闭服务器 try { Log.v(TAG, Thread.currentThread().getName() + "---->" + "serverSocket.close()"); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } Log.v(TAG, Thread.currentThread().getName() + "---->" + "**************** onDestroy****************"); } @Override public void onStart(Intent intent, int startId) { Log.d(TAG, Thread.currentThread().getName() + "---->" + " onStart()"); super.onStart(intent, startId); } @Override public IBinder onBind(Intent arg0) { Log.d(TAG, " onBind"); return null; } } package com.otheri.service; import java.io.File; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.util.Log; /** * 设置:android 手机 * * * */ public class androidService extends Service { public static final String TAG = "TAG"; public static Boolean mainThreadFlag = true; public static Boolean ioThreadFlag = true; ServerSocket serverSocket = null; final int SERVER_PORT = 10086; File testFile; private sysBroadcastReceiver sysBR; @Override public void onCreate() { super.onCreate(); Log.v(TAG, Thread.currentThread().getName() + "---->" + " onCreate"); /* 创建内部类 sysBroadcastReceiver 并注册 registerReceiver */ sysRegisterReceiver(); new Thread() { public void run() { doListen(); }; }.start(); } private void doListen() { Log.d(TAG, Thread.currentThread().getName() + "---->" + " doListen() START"); serverSocket = null; try { Log.d(TAG, Thread.currentThread().getName() + "---->" + " doListen() new serverSocket"); serverSocket = new ServerSocket(SERVER_PORT); boolean mainThreadFlag = true; while (mainThreadFlag) { Log.d(TAG, Thread.currentThread().getName() + "---->" + " doListen() listen"); Socket client = serverSocket.accept(); new Thread(new ThreadReadWriterIOSocket(this, client)).start(); } } catch (IOException e1) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "new serverSocket error"); e1.printStackTrace(); } } /* 创建内部类 sysBroadcastReceiver 并注册 registerReceiver */ private void sysRegisterReceiver() { Log.v(TAG, Thread.currentThread().getName() + "---->" + "sysRegisterReceiver"); sysBR = new sysBroadcastReceiver(); /* 注册 BroadcastReceiver */ IntentFilter filter1 = new IntentFilter(); /* 新的应用程序被安装到了设备上的广播 */ filter1.addAction("android.intent.action.PACKAGE_ADDED"); filter1.addDataScheme("package"); filter1.addAction("android.intent.action.PACKAGE_REMOVED"); filter1.addDataScheme("package"); registerReceiver(sysBR, filter1); } /* 内部类:BroadcastReceiver 用于接收系统事件 */ private class sysBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equalsIgnoreCase("android.intent.action.PACKAGE_ADDED")) { // ReadInstalledAPP(); } else if (action .equalsIgnoreCase("android.intent.action.PACKAGE_REMOVED")) { // ReadInstalledAPP(); } Log.v(TAG, Thread.currentThread().getName() + "---->" + "sysBroadcastReceiver onReceive"); } } @Override public void onDestroy() { super.onDestroy(); // 关闭线程 mainThreadFlag = false; ioThreadFlag = false; // 关闭服务器 try { Log.v(TAG, Thread.currentThread().getName() + "---->" + "serverSocket.close()"); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } Log.v(TAG, Thread.currentThread().getName() + "---->" + "**************** onDestroy****************"); } @Override public void onStart(Intent intent, int startId) { Log.d(TAG, Thread.currentThread().getName() + "---->" + " onStart()"); super.onStart(intent, startId); } @Override public IBinder onBind(Intent arg0) { Log.d(TAG, " onBind"); return null; } } 用于接收 PC 发来的 Broastcast 并启动主类 service 的 ServiceBroadcastReceiver.java view plaincopy to clipboardprint? package com.otheri.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class ServiceBroadcastReceiver extends BroadcastReceiver { private static String START_ACTION = "NotifyServiceStart"; private static String STOP_ACTION = "NotifyServiceStop"; @Override public void onReceive(Context context, Intent intent) { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive"); String action = intent.getAction(); if (START_ACTION.equalsIgnoreCase(action)) { context.startService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive start end"); } else if (STOP_ACTION.equalsIgnoreCase(action)) { context.stopService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive stop end"); } } } package com.otheri.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class ServiceBroadcastReceiver extends BroadcastReceiver { private static String START_ACTION = "NotifyServiceStart"; private static String STOP_ACTION = "NotifyServiceStop"; @Override public void onReceive(Context context, Intent intent) { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive"); String action = intent.getAction(); if (START_ACTION.equalsIgnoreCase(action)) { context.startService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive start end"); } else if (STOP_ACTION.equalsIgnoreCase(action)) { context.stopService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive stop end"); } } } 用于新 socket 连接的读写线程类 ThreadReadWriterIOSocket.java view plaincopy to clipboardprint? package com.otheri.service; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import android.content.Context; import android.util.Log; import com.otheri.util.FileHelper; import com.otheri.util.MyUtil; /** * 功能:用于 socket 的交互 * * @author wufenglong * */ public class ThreadReadWriterIOSocket implements Runnable { private Socket client; private Context context; ThreadReadWriterIOSocket(Context context, Socket client) { this.client = client; this.context = context; } @Override public void run() { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "a client has connected to server!"); BufferedOutputStream out; BufferedInputStream in; try { /* PC 端发来的数据 msg */ String currCMD = ""; out = new BufferedOutputStream(client.getOutputStream()); in = new BufferedInputStream(client.getInputStream()); // testSocket();// 测试 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) { try { if (!client.isConnected()) { break; } /* 接收 PC 发来的数据 */ Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "will read......"); /* 读操作命令 */ currCMD = readCMDFromSocket(in); Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "**currCMD ==== " + currCMD); /* 根据命令分别处理数据 */ if (currCMD.equals("1")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("2")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("3")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("4")) { /* 准备接收文件数据 */ try { out.write("service receive OK".getBytes()); out.flush(); } catch (IOException e) { e.printStackTrace(); } /* 接收文件数据,4 字节文件长度,4 字节文件格式,其后是文 件数据 */ byte[] filelength = new byte[4]; byte[] fileformat = new byte[4]; byte[] filebytes = null; /* 从 socket 流中读取完整文件数据 */ filebytes = receiveFileFromSocket(in, out, filelength, fileformat); // Log.v(Service139.TAG, "receive data =" + new // String(filebytes)); try { /* 生成文件 */ File file = FileHelper.newFile("R0013340.JPG"); FileHelper.writeFile(file, filebytes, 0, filebytes.length); } catch (IOException e) { e.printStackTrace(); } } else if (currCMD.equals("exit")) { } } catch (Exception e) { // try { // out.write("error".getBytes("utf-8")); // out.flush(); // } catch (IOException e1) { // e1.printStackTrace(); // } Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error111111"); } } out.close(); in.close(); } catch (Exception e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error222222"); e.printStackTrace(); } finally { try { if (client != null) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "client.close()"); client.close(); } } catch (IOException e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error333333"); e.printStackTrace(); } } } /** * 功能:从 socket 流中读取完整文件数据 * * InputStream in:socket 输入流 * * byte[] filelength: 流的前 4 个字节存储要转送的文件的字节数 * * byte[] fileformat:流的前 5-8 字节存储要转送的文件的格式(如.apk) * * */ public static byte[] receiveFileFromSocket(InputStream in, OutputStream out, byte[] filelength, byte[] fileformat) { byte[] filebytes = null;// 文件数据 try { in.read(filelength);// 读文件长度 int filelen = MyUtil.bytesToInt(filelength);// 文件长度从 4 字节 byte[]转成 Int String strtmp = "read file length ok:" + filelen; out.write(strtmp.getBytes("utf-8")); out.flush(); filebytes = new byte[filelen]; int pos = 0; int rcvLen = 0; while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) { pos += rcvLen; } Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "read file OK:file size=" + filebytes.length); out.write("read file ok".getBytes("utf-8")); out.flush(); } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "receiveFileFromSocket error"); e.printStackTrace(); } return filebytes; } /* 读取命令 */ public static String readCMDFromSocket(InputStream in) { int MAX_BUFFER_BYTES = 2048; String msg = ""; byte[] tempbuffer = new byte[MAX_BUFFER_BYTES]; try { int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length); msg = new String(tempbuffer, 0, numReadedBytes, "utf-8"); tempbuffer = null; } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "readFromSocket error"); e.printStackTrace(); } // Log.v(Service139.TAG, "msg=" + msg); return msg; } } package com.otheri.service; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import android.content.Context; import android.util.Log; import com.otheri.util.FileHelper; import com.otheri.util.MyUtil; /** * 功能:用于 socket 的交互 * * @author wufenglong * */ public class ThreadReadWriterIOSocket implements Runnable { private Socket client; private Context context; ThreadReadWriterIOSocket(Context context, Socket client) { this.client = client; this.context = context; } @Override public void run() { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "a client has connected to server!"); BufferedOutputStream out; BufferedInputStream in; try { /* PC 端发来的数据 msg */ String currCMD = ""; out = new BufferedOutputStream(client.getOutputStream()); in = new BufferedInputStream(client.getInputStream()); // testSocket();// 测试 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) { try { if (!client.isConnected()) { break; } /* 接收 PC 发来的数据 */ Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "will read......"); /* 读操作命令 */ currCMD = readCMDFromSocket(in); Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "**currCMD ==== " + currCMD); /* 根据命令分别处理数据 */ if (currCMD.equals("1")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("2")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("3")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("4")) { /* 准备接收文件数据 */ try { out.write("service receive OK".getBytes()); out.flush(); } catch (IOException e) { e.printStackTrace(); } /* 接收文件数据,4 字节文件长度,4 字节文件格式,其后是文 件数据 */ byte[] filelength = new byte[4]; byte[] fileformat = new byte[4]; byte[] filebytes = null; /* 从 socket 流中读取完整文件数据 */ filebytes = receiveFileFromSocket(in, out, filelength, fileformat); // Log.v(Service139.TAG, "receive data =" + new // String(filebytes)); try { /* 生成文件 */ File file = FileHelper.newFile("R0013340.JPG"); FileHelper.writeFile(file, filebytes, 0, filebytes.length); } catch (IOException e) { e.printStackTrace(); } } else if (currCMD.equals("exit")) { } } catch (Exception e) { // try { // out.write("error".getBytes("utf-8")); // out.flush(); // } catch (IOException e1) { // e1.printStackTrace(); // } Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error111111"); } } out.close(); in.close(); } catch (Exception e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error222222"); e.printStackTrace(); } finally { try { if (client != null) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "client.close()"); client.close(); } } catch (IOException e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error333333"); e.printStackTrace(); } } } /** * 功能:从 socket 流中读取完整文件数据 * * InputStream in:socket 输入流 * * byte[] filelength: 流的前 4 个字节存储要转送的文件的字节数 * * byte[] fileformat:流的前 5-8 字节存储要转送的文件的格式(如.apk) * * */ public static byte[] receiveFileFromSocket(InputStream in, OutputStream out, byte[] filelength, byte[] fileformat) { byte[] filebytes = null;// 文件数据 try { in.read(filelength);// 读文件长度 int filelen = MyUtil.bytesToInt(filelength);// 文件长度从 4 字节 byte[]转成 Int String strtmp = "read file length ok:" + filelen; out.write(strtmp.getBytes("utf-8")); out.flush(); filebytes = new byte[filelen]; int pos = 0; int rcvLen = 0; while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) { pos += rcvLen; } Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "read file OK:file size=" + filebytes.length); out.write("read file ok".getBytes("utf-8")); out.flush(); } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "receiveFileFromSocket error"); e.printStackTrace(); } return filebytes; } /* 读取命令 */ public static String readCMDFromSocket(InputStream in) { int MAX_BUFFER_BYTES = 2048; String msg = ""; byte[] tempbuffer = new byte[MAX_BUFFER_BYTES]; try { int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length); msg = new String(tempbuffer, 0, numReadedBytes, "utf-8"); tempbuffer = null; } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "readFromSocket error"); e.printStackTrace(); } // Log.v(Service139.TAG, "msg=" + msg); return msg; } } 后面是两个辅助类: view plaincopy to clipboardprint? package com.otheri.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import com.otheri.service.androidService; import android.util.Log; public class FileHelper { // private static String FILEPATH = "/data/local/tmp"; private static String FILEPATH = "/sdcard"; // private static String FILEPATH = "/tmp"; public static File newFile(String fileName) { File file = null; try { file = new File(FILEPATH, fileName); file.delete(); file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return file; } public static void writeFile(File file, byte[] data, int offset, int count) throws IOException { FileOutputStream fos = new FileOutputStream(file, true); fos.write(data, offset, count); fos.flush(); fos.close(); } public static byte[] readFile(String fileName) throws IOException { File file = new File(FILEPATH, fileName); file.createNewFile(); FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); int leng = bis.available(); Log.v(androidService.TAG, "filesize = " + leng); byte[] b = new byte[leng]; bis.read(b, 0, leng); // Input in = new Input(fis); // byte[] ret = in.readAll(); // in.close(); bis.close(); return b; } } package com.otheri.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import com.otheri.service.androidService; import android.util.Log; public class FileHelper { // private static String FILEPATH = "/data/local/tmp"; private static String FILEPATH = "/sdcard"; // private static String FILEPATH = "/tmp"; public static File newFile(String fileName) { File file = null; try { file = new File(FILEPATH, fileName); file.delete(); file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return file; } public static void writeFile(File file, byte[] data, int offset, int count) throws IOException { FileOutputStream fos = new FileOutputStream(file, true); fos.write(data, offset, count); fos.flush(); fos.close(); } public static byte[] readFile(String fileName) throws IOException { File file = new File(FILEPATH, fileName); file.createNewFile(); FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); int leng = bis.available(); Log.v(androidService.TAG, "filesize = " + leng); byte[] b = new byte[leng]; bis.read(b, 0, leng); // Input in = new Input(fis); // byte[] ret = in.readAll(); // in.close(); bis.close(); return b; } } view plaincopy to clipboardprint? package com.otheri.util; import java.io.InputStream; import android.util.Log; import com.otheri.service.androidService; public class MyUtil { /* byte[]转 Int */ public static int bytesToInt(byte[] bytes) { int addr = bytes[0] & 0xFF; addr |= ((bytes[1] << 8) & 0xFF00); addr |= ((bytes[2] << 16) & 0xFF0000); addr |= ((bytes[3] << 24) & 0xFF000000); return addr; } /* Int 转 byte[] */ public static byte[] intToByte(int i) { byte[] abyte0 = new byte[4]; abyte0[0] = (byte) (0xff & i); abyte0[1] = (byte) ((0xff00 & i) >> 8); abyte0[2] = (byte) ((0xff0000 & i) >> 16); abyte0[3] = (byte) ((0xff000000 & i) >> 24); return abyte0; } } 本文来自 CSDN 博客,转载请标明出处: http://blog.csdn.net/wufenglong/archive/2010/07/31/5778862.aspx
还剩36页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf