


版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、PC 客戶端與 Android 服務(wù)端的 Socket 同步通信( USB) 收藏 需求:1. 一個 android 端的 service 后臺運行的程序, 作為 socket 的服務(wù)器端 ;用于接收 Pc client 端發(fā)來的命令,來處理數(shù)據(jù)后,把結(jié)果發(fā)給 PC client2. PC 端程序,作為 socket 的客戶端,用于給 android 手機端發(fā)操作命令難點分析:1手機一定要有adb模式,即插上 USB線時馬上提示的對話框選adb。好多對手機的操作都可以用 adb 直接作。不過,我發(fā)現(xiàn) LG GW880 就沒有,要去下載個2. android 默認手機端的 IP 為“127.0.
2、0.1”3. 要想聯(lián)通PC與an droid手機的sokcet, 定要用adb forward來作下端口轉(zhuǎn)發(fā)才能連 上 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 端的 servic
3、e 程序 Install 到手機上容易,但是還要有方法來從 PC 的 client 端來啟動手機上的 service ,這個辦法可以通過 PC 端 adb 命令來發(fā)一個 Broastcast ,手機 端再寫個接收 BroastcastReceive來接收這個 Broastcast,在這個 BroastcastReceive來啟動servicepc 端命令:view plaincopy to clipboardprint?Runtime.getRuntime().exec("adb shell am broadcast -a NotifyServiceStart");Runt
4、ime.getRuntime().exec("adb shell am broadcast -a NotifyServiceStart");android 端的代碼 :ServiceBroadcastReceiver.javaview plaincopy to clipboardprint?package com.otheri.service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.
5、util.Log;public class ServiceBroadcastReceiver extends BroadcastReceiver private static String START_ACTION = "NotifyServiceStart" private static String STOP_ACTION = "NotifyServiceStop"Overridepublic void onReceive(Context context, Intent intent) Log.d(androidService.TAG , Threa
6、d.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() + &q
7、uot;>"+ "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 onRec
8、eive 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&
9、quot; private static String STOP_ACTION = "NotifyServiceStop"Overridepublic void onReceive(Context context, Intent intent) Log.d(androidService.TAG , Thread.currentThread().getName() + ">"+ "ServiceBroadcastReceiver onReceive");String action = intent.getAction();if (
10、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.stopSe
11、rvice(new Intent(context, androidService.class); Log.d(androidService.TAG , Thread.currentThread().getName() + ">"+ "ServiceBroadcastReceiver onReceive stop end");5. 由于是 USB 連接,所以 socket 就可以設(shè)計為一但連接就一直聯(lián)通,即在new socket 和開完 out,in 流后,就用個 while(true) 來循環(huán) PC 端和 android 端的讀和寫android
12、的代碼: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 端發(fā)來的數(shù)據(jù) msg */String currCMD = ""out = new Buffered
13、OutputStream(client.getOutputStream();in = new BufferedInputStream(client.getInputStream();/ testSocket();/ 測試 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) try if (!client.isConnected() break;/* 接收 PC 發(fā)來的數(shù)據(jù) */Log.v(androidService.TAG , Thread.currentThread().getN
14、ame()+ ">" + "will read");/* 讀操作命令 */ currCMD = readCMDFromSocket(in);Log.v(androidService.TAG , Thread.currentThread().getName()+ ">" + "*currCMD = " + currCMD);/* 根據(jù)命令分別處理數(shù)據(jù) */if (currCMD.equals("1") out.write("OK".getBytes(); out.f
15、lush(); 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") /* 準備接收文件數(shù)據(jù) */ try out.write("service receive OK".getBytes(); out
16、.flush(); catch (IOException e) e.printStackTrace();件數(shù)據(jù) */* 接收文件數(shù)據(jù), 4字節(jié)文件長度, 4 字節(jié)文件格式,其后是文byte filelength = new byte4; byte fileformat = new byte4; byte filebytes = null;/* 從 socket 流中讀取完整文件數(shù)據(jù) */ filebytes = receiveFileFromSocket(in, out, filelength, fileformat);/ Log.v(Service139.TAG , "receiv
17、e 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("
18、;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 , Threa
19、d.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(androidSer
20、vice.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;BufferedI
21、nputStream in;try /* PC 端發(fā)來的數(shù)據(jù) msg */ String currCMD = "" out = new BufferedOutputStream(client.getOutputStream(); in = new BufferedInputStream(client.getInputStream();/ testSocket();/ 測試 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) try if (!client.isCo
22、nnected() break;/* 接收 PC 發(fā)來的數(shù)據(jù) */Log.v(androidService.TAG , Thread.currentThread().getName() + ">" + "will read");/* 讀操作命令 */ currCMD = readCMDFromSocket(in); Log.v(androidService.TAG, Thread.currentThread().getName()+ ">" + "*currCMD = " + currCMD);/* 根
23、據(jù)命令分別處理數(shù)據(jù) */ 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(&
24、quot;4") /* 準備接收文件數(shù)據(jù) */ try out.write("service receive OK".getBytes(); out.flush(); catch (IOException e) e.printStackTrace();件數(shù)據(jù) */* 接收文件數(shù)據(jù), 4字節(jié)文件長度, 4 字節(jié)文件格式,其后是文byte filelength = new byte4; byte fileformat = new byte4; byte filebytes = null;/* 從 socket 流中讀取完整文件數(shù)據(jù) */ filebytes = rec
25、eiveFileFromSocket(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()
26、; 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 error11111
27、1"); 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()+ ">&quo
28、t; + "client.close()");client.close(); catch (IOException e) Log.e(androidService.TAG, Thread.currentThread().getName()+ ">" + "read write error333333");e.printStackTrace();6. 如果是在 PC 端和 android 端的讀寫操作來 while(true) 循環(huán), 這樣 socket 流的結(jié)尾不好 判斷,不能用 “-1”來判斷,因為 “-1”是只有在 sock
29、et 關(guān)閉時才作為判斷結(jié)尾。7. socket 在 out.write(bytes); 時,要是數(shù)據(jù)太大時,超過 socket 的緩存, socket 自動分包發(fā) 送,所以對方就一定要用循環(huán)來多次讀。 最好的辦法就是服務(wù)器和客戶端協(xié)議好, 比如發(fā)文 件時,先寫過來一個要發(fā)送的文件的大小,然后再發(fā)送文件;對方用這個大小,來循環(huán)讀取數(shù)據(jù)。android 端接收數(shù)據(jù)的代碼view plaincopy to clipboardprint?/* 功能:從 socket 流中讀取完整文件數(shù)據(jù)* InputStream in : socket 輸入流* byte filelength: 流的前 4 個字節(jié)存
30、儲要轉(zhuǎn)送的文件的字節(jié)數(shù)*.apk)* byte fileformat :流的前 5-8 字節(jié)存儲要轉(zhuǎn)送的文件的格式(如public static byte receiveFileFromSocket(InputStream in,OutputStream out, byte filelength, byte fileformat) byte filebytes = null;/ 文件數(shù)據(jù) try int filelen = MyUtil.bytesToInt(filelength);/ 文件長度從 4 字節(jié) byte 轉(zhuǎn)成 Int String strtmp = "read file
31、 length ok:" + filelen; out.write(strtmp.getBytes("utf-8");out.flush();filebytes = new bytefilelen;int pos = 0;int rcvLen = 0;while (rcvLen = in.read(filebytes, pos, filelen - pos) > 0) pos += rcvLen;Log.v(androidService.TAG , Thread.currentThread().getName() + ">" + &
32、quot;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
33、filebytes;* 功能:從 socket 流中讀取完整文件數(shù)據(jù)* InputStream in : socket 輸入流* byte filelength: 流的前 4 個字節(jié)存儲要轉(zhuǎn)送的文件的字節(jié)數(shù)*.apk)* byte fileformat :流的前 5-8 字節(jié)存儲要轉(zhuǎn)送的文件的格式(如*public static byte receiveFileFromSocket(InputStream in, OutputStream out, byte filelength, byte fileformat) byte filebytes = null;/ 文件數(shù)據(jù)try int fil
34、elen = MyUtil.bytesToInt(filelength);/ 文件長度從 4 字節(jié) byte 轉(zhuǎn)成 Int String strtmp = "read file length ok:" + filelen; out.write(strtmp.getBytes("utf-8");out.flush();filebytes = new bytefilelen;int pos = 0;int rcvLen = 0;while (rcvLen = in.read(filebytes, pos, filelen - pos) > 0) pos
35、 += 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().getNa
36、me()+ ">" + "receiveFileFromSocket error");e.printStackTrace();return filebytes;8. socket 的最重要的機制就是讀寫采用的是阻塞的方式,如果客戶端作為命令發(fā)起者,服 務(wù)器端作為接收者的話,只有當客戶端 client 用 out.writer() 寫到輸出流里后,即流中有數(shù)據(jù) service的read才會執(zhí)行,不然就會一直停在read()那里等數(shù)據(jù)。源碼:客戶端( pc 端):testPcClient.javaview plaincopy to clipboardp
37、rint?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 .InetAddress;import .Socket;import .UnknownHostException;public
38、 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&
39、quot;); 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("");System.out.
40、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();BufferedInputStre
41、am in = new BufferedInputStream(socket .getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader( System.in);boolean flag = true;while (flag) System.out.print(" 請輸入 16 的數(shù)字 ,退出輸入 exit :"); String strWord = br.readLine();/ 從控制臺輸入 16 if (strWord.equals("1") out.
42、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:rn"+ strFormsocket);System.out .println("= "); else if (strWord.equals("2") ou
43、t.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:rn"+ strFormsocket);System.out .println("= "); else if (strWord.equals("3")
44、 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:rn" + strFormsocket);System.out .println("= ="); else if (strWord.equals("4&q
45、uot;) /* 發(fā)送命令 */out.write("4".getBytes();out.flush();System.out.println("send file finish sending the CMD : ");/* 服務(wù)器反饋:準備接收 */String strFormsocket = readFromSocket(in);System.out.println("service ready receice data:UPDATE_CONTACTS:" + strFormsocket);byte filebytes = Fi
46、leHelper.readFile("R0013340.JPG");System.out.println("file size=" + filebytes.length);/* 將整數(shù)轉(zhuǎn)成 4 字節(jié) byte 數(shù)組 */byte filelength = new byte4;filelength = ToByte(filebytes.length);/*將.apk字符串轉(zhuǎn)成4字節(jié)byte數(shù)組*/byte fileformat = null; fileformat = ".apk".getBytes();System.
47、out.println("fileformat length=" + fileformat.length);/* 字節(jié)流中前 4 字節(jié)為文件長度, 4 字節(jié)文件格式, 以后是文件流 */ /* 注意如果 write 里的 byte 超過 socket 的緩存,系統(tǒng)自動分包寫過 去,所以對方要循環(huán)寫完 */out.write(filelength);out.flush();String strok1 = readFromSocket(in);System.out.println("service receive filelength :" + strok1
48、);/ 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("*");/* 服務(wù)器反饋:接收成功 */String strre
49、ad = 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 strForms
50、ocket = readFromSocket(in); System.out.println("the data sent by server is:rn" + strFormsocket);flag = false;System.out .println("= ="); catch (UnknownHostException e1) System.out.println("TCP 331133" + "ERROR:" + e1.toString(); catch (Exception e2) System.out
51、.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 流中讀數(shù)據(jù) */public sta
52、tic String readFromSocket(InputStream in) int MAX_BUFFER_BYTES = 4000;String msg = ""byte tempbuffer = new byteMAX_BUFFER_BYTES;try int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length); msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");tempbuffer = null; catch (E
53、xception 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.I
54、nputStreamReader;import .InetAddress;import .Socket;import .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"
55、;);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 ser
56、verAddr = null;serverAddr = InetAddress.getByName("");System.out.println("TCP 1111" + "C: Connecting."); socket = new Socket(serverAddr, 12580);String str = "hi,wufenglong"System.out.println("TCP 221122" + "C:RECEIVE");BufferedOutp
57、utStream 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(" 請輸入 16 的數(shù)字 ,退出輸入 exit :")
58、;String strWord = br.readLine();/ 從控制臺輸入 16if (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:rn" + strFormsoc
59、ket);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:rn" + strForms
60、ocket);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:rn" + strFormsocket);System.out.println("="); else if (strWord.equals("4") /* 發(fā)送命令 */ out.write("4".getBytes(); out.flush();S
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 地理-2025年中考考前最后一卷試題押題猜想(陜西卷)
- 中國古代文學(xué)作品選筆記
- 初中數(shù)學(xué)九年級下冊統(tǒng)編教案 8.2貨比三家
- DeepSeek+AI大模型在工程造價領(lǐng)域的智能化解決方案
- 內(nèi)蒙古自治區(qū)錫林郭勒盟三縣聯(lián)考2025屆九年級下學(xué)期中考三模數(shù)學(xué)試卷(含詳解)
- 洗胃試題及答案
- 五官考試題及答案
- 河南省商丘市夏邑縣2025年九年級下學(xué)期模擬考試英語試卷(文字版含答案)
- 2025年四川省瀘州市江陽區(qū)初中學(xué)業(yè)水平適應(yīng)性考試生物學(xué)試題 (含解析)
- 2025個人汽車貸款合同常用版
- T-ISEAA 001-2020 網(wǎng)絡(luò)安全等級保護測評高風(fēng)險判定指引
- 護理查房慢性腎臟病5期護理查房
- 鉆越保阜高速公路施工方案
- GMS基礎(chǔ)知識的教案
- 第5章 鋼梁計算原理
- 中醫(yī)藥法試題及答案
- 籃球規(guī)則簡介課件PPT模板下載
- GB/T 3452.4-2020液壓氣動用O形橡膠密封圈第4部分:抗擠壓環(huán)(擋環(huán))
- GB/T 20523-2006企業(yè)物流成本構(gòu)成與計算
- GA 44-2015消防頭盔
- 西南科技大學(xué)機械原理期末考試復(fù)習(xí)題及答案
評論
0/150
提交評論