PC 与 Android 的adb同步通信(一)

公司只能上csdn,作为中转站传资料。原文地址http://www.yidin.net/discuz/forum.php?mod=viewthread&tid=172&extra=page%3D1

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.

  1. Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); 
  2. Thread.sleep(3000);
复制代码
4.android端的service程序Install到手机上容易,但是还要有方法来从PC的client端来启动手机上的service ,这个办法可以通过PC端adb命令来发一个Broastcast ,手机端再写个接收BroastcastReceive来接收这个Broastcast,在这个BroastcastReceive来启动service

        pc端命令:
  1. Runtime.getRuntime().exec( 
  2. "adb shell am broadcast -a NotifyServiceStart");
复制代码
android端的代码:ServiceBroadcastReceiver.java

  1. package eoe.otheri.service; 


  2. import android.content.BroadcastReceiver; 
  3. import android.content.Context; 
  4. import android.content.Intent; 
  5. import android.util.Log; 


  6. public class ServiceBroadcastReceiver extends BroadcastReceiver { 
  7. private static String START_ACTION = "NotifyServiceStart"; 
  8. private static String STOP_ACTION = "NotifyServiceStop"; 


  9. @Override 
  10. public void onReceive(Context context, Intent intent) { 
  11. Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" 
  12. + "ServiceBroadcastReceiver onReceive"); 
  13. String action = intent.getAction(); 
  14. if (START_ACTION.equalsIgnoreCase(action)) { 
  15. context.startService(new Intent(context, androidService.class)); 
  16. Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" 
  17. + "ServiceBroadcastReceiver onReceive start end"); 
  18. } else if (STOP_ACTION.equalsIgnoreCase(action)) { 
  19. context.stopService(new Intent(context, androidService.class)); 
  20. Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" 
  21. + "ServiceBroadcastReceiver onReceive stop end"); 





复制代码
5.由于是USB连接,所以socket就可以设计为一但连接就一直联通,即在new socket和开完out,in流后,就用个while(true){}来循环PC端和android端的读和写

        android的代码:

  1. public void run() { 
  2. Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" 
  3. + "a client has connected to server!"); 
  4. BufferedOutputStream out; 
  5. BufferedInputStream in; 
  6. try { 
  7. /* PC端发来的数据msg */ 
  8. String currCMD = ""; 
  9. out = new BufferedOutputStream(client.getOutputStream()); 
  10. in = new BufferedInputStream(client.getInputStream()); 
  11. // testSocket();// 测试socket方法 
  12. androidService.ioThreadFlag = true; 
  13. while (androidService.ioThreadFlag) { 
  14. try { 
  15. if (!client.isConnected()) { 
  16. break; 



  17. /* 接收PC发来的数据 */ 
  18. Log.v(androidService.TAG, Thread.currentThread().getName() 
  19. + "---->" + "will read......"); 
  20. /* 读操作命令 */ 
  21. currCMD = readCMDFromSocket(in); 
  22. Log.v(androidService.TAG, Thread.currentThread().getName() 
  23. + "---->" + "**currCMD ==== " + currCMD); 


  24. /* 根据命令分别处理数据 */ 
  25. if (currCMD.equals("1")) { 
  26. out.write("OK".getBytes()); 
  27. out.flush(); 
  28. } else if (currCMD.equals("2")) { 
  29. out.write("OK".getBytes()); 
  30. out.flush(); 
  31. } else if (currCMD.equals("3")) { 
  32. out.write("OK".getBytes()); 
  33. out.flush(); 
  34. } else if (currCMD.equals("4")) { 


  35. /* 准备接收文件数据 */ 
  36. try { 
  37. out.write("service receive OK".getBytes()); 
  38. out.flush(); 
  39. } catch (IOException e) { 
  40. e.printStackTrace(); 



  41. /* 接收文件数据,4字节文件长度,4字节文件格式,其后是文件数据 */ 
  42. byte[] filelength = new byte[4]; 
  43. byte[] fileformat = new byte[4]; 
  44. byte[] filebytes = null; 


  45. /* 从socket流中读取完整文件数据 */ 
  46. filebytes = receiveFileFromSocket(in, out, filelength,fileformat); 
  47. // Log.v(Service139.TAG, "receive data =" + new 
  48. // String(filebytes)); 
  49. try { 


  50. /* 生成文件 */ 
  51. File file = FileHelper.newFile("R0013340.JPG"); 
  52. FileHelper.writeFile(file, filebytes, 0, 
  53. filebytes.length); 
  54. } catch (IOException e) { 
  55. e.printStackTrace(); 

  56. } else if (currCMD.equals("exit")) { 

  57. } catch (Exception e) { 
  58. // try { 
  59. // out.write("error".getBytes("utf-8")); 
  60. // out.flush(); 
  61. // } catch (IOException e1) { 
  62. // e1.printStackTrace(); 
  63. // } 
  64. Log.e(androidService.TAG, Thread.currentThread().getName() 
  65. + "---->" + "read write error111111"); 


  66. out.close(); 
  67. in.close(); 
  68. } catch (Exception e) { 
  69. Log.e(androidService.TAG, Thread.currentThread().getName() 
  70. + "---->" + "read write error222222"); 
  71. e.printStackTrace(); 
  72. } finally { 
  73. try { 
  74. if (client != null) { 
  75. Log.v(androidService.TAG, Thread.currentThread().getName() 
  76. + "---->" + "client.close()"); 
  77. client.close(); 

  78. } catch (IOException e) { 
  79. Log.e(androidService.TAG, Thread.currentThread().getName() 
  80. + "---->" + "read write error333333"); 
  81. e.printStackTrace(); 


复制代码
6.如果是在PC端和android端的读写操作来while(true){}循环,这样socket流的结尾不好判断,不能用“-1”来判断,因为“-1”是只有在socket关闭时才作为判断结尾。
       7.socket在out.write(bytes);时,要是数据太大时,超过socket的缓存,socket自动分包发送,所以对方就一定要用循环来多次读。最好的办法就是服务器和客户端协议好,比如发文件时,先写过来一个要发送的文件的大小,然后再发送文件;对方用这个大小,来循环读取数据。

       android端接收数据的代码:
  1. /** 
  2. * 功能:从socket流中读取完整文件数据 

  3. * InputStream in:socket输入流 

  4. * byte[] filelength: 流的前4个字节存储要转送的文件的字节数 

  5. * byte[] fileformat:流的前5-8字节存储要转送的文件的格式(如.apk) 

  6. * */ 
  7. public static byte[] receiveFileFromSocket(InputStream in, 
  8. OutputStream out, byte[] filelength, byte[] fileformat) { 
  9. byte[] filebytes = null;// 文件数据 
  10. try { 
  11. int filelen = MyUtil.bytesToInt(filelength);// 文件长度从4字节byte[]转成Int 
  12. String strtmp = "read file length ok:" + filelen; 
  13. out.write(strtmp.getBytes("utf-8")); 
  14. out.flush(); 
  15. filebytes = new byte[filelen]; 
  16. int pos = 0; 
  17. int rcvLen = 0; 
  18. while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) { 
  19. pos += rcvLen; 

  20. Log.v(androidService.TAG, Thread.currentThread().getName() 
  21. + "---->" + "read file OK:file size=" + filebytes.length); 
  22. out.write("read file ok".getBytes("utf-8")); 
  23. out.flush(); 
  24. } catch (Exception e) { 
  25. Log.v(androidService.TAG, Thread.currentThread().getName() 
  26. + "---->" + "receiveFileFromSocket error"); 
  27. e.printStackTrace(); 

  28. return filebytes; 

复制代码
8.socket的最重要的机制就是读写采用的是阻塞的方式,如果客户端作为命令发起者,服务器端作为接收者的话,只有当客户端client用out.writer()写到输出流里后,即流中有数据service的read才会执行,不然就会一直停在read()那里等数据。

        9.还要让服务器端可以同时连接多个client,即服务器端用new thread()来作数据读取操作。

你可能感兴趣的:(PC 与 Android 的adb同步通信(一))