當前位置:
首頁 > 最新 > 吊炸天之Android 如何實現無網路傳輸文件

吊炸天之Android 如何實現無網路傳輸文件

作者:葉應是葉

最近的項目需要實現一個 Android 手機之間無網路傳輸文件的功能,就發現了 Wifi P2P(Wifi點對點)這麼一個功能,最後也實現了通過 Wifi隔空傳輸文件的功能,這裡我也來整理下代碼,分享給大家。

Wifi P2P 是在 Android 4.0 以及更高版本系統中加入的功能,通過 Wifi P2P 可以在不連接網路的情況下,直接與配對的設備進行數據交換。相對於藍牙,Wifi P2P 的搜索速度和傳輸速度更快,傳輸距離更遠

實現的效果如下所示:

一般而言,開發步驟分為以下幾點:

在 AndroidManifest 中聲明相關許可權(網路和文件讀寫許可權)

獲取 WifiP2pManager ,註冊相關廣播監聽Wifi直連的狀態變化

指定某一台設備為伺服器(用來接收文件),創建群組並作為群主存在,在指定埠監聽客戶端的連接請求,等待客戶端發起連接請求以及文件傳輸請求

客戶端(用來發送文件)主動搜索附近的設備,加入到伺服器創建的群組,獲取伺服器的IP地址,向其發起文件傳輸請求

校驗文件完整性

一、聲明許可權

Wifi P2P 技術並不會訪問網路,但由於會使用到 Java socket,所以需要申請網路許可權。此外,由於是要實現文件互傳,所以也需要申請SD卡讀寫許可權。

二、註冊廣播

與 Wifi P2P 相關的廣播有以下幾個:

WIFI_P2P_STATE_CHANGED_ACTION( 用於指示 Wifi P2P 是否可用 )

WIFI_P2P_PEERS_CHANGED_ACTION( 對等節點列表發生了變化 )

WIFI_P2P_CONNECTION_CHANGED_ACTION( Wifi P2P 的連接狀態發生了改變 )

WIFI_P2P_THIS_DEVICE_CHANGED_ACTION( 本設備的設備信息發生了變化 )

當接收到這幾個廣播時,我們都需要到 WifiP2pManager (對等網路管理器)來進行相應的信息請求,此外還需要用到 Channel 對象作為請求參數

當收到WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION廣播時,可以判斷當前 Wifi P2P是否可用

當收到WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION廣播時,意味設備周圍的可用設備列表發生了變化,可以通過requestPeers方法得到可用的設備列表,之後就可以選擇當中的某一個設備進行連接操作

當收到WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION廣播時,意味著 Wifi P2P 的連接狀態發生了變化,可能是連接到了某設備,或者是與某設備斷開了連接

如果是與某設備連接上了,則可以通過requestConnectionInfo方法獲取到連接信息

當收到WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION廣播時,則可以獲取到本設備變化後的設備信息

可以看出 Wifi P2P 的介面高度非同步化,到現在已經用到了三個系統的回調函數,一個用於 WifiP2pManager 的初始化,兩個用於在廣播中非同步請求數據,為了簡化操作,此處統一使用一個自定義的回調函數,方法含義與系統的回調函數一致

所以,整個廣播接收器使用到的所有代碼是:

三、伺服器端創建群組

假設當設備A搜索到了設備B,並與設備B連接到了一起,此時系統會自動創建一個群組(Group)並隨機指定一台設備為群主(GroupOwner)。此時,對於兩台設備來說,群主的IP地址是可知的(系統回調函數中有提供),但客戶端的IP地址需要再來通過其他方法來主動獲取。例如,可以在設備連接成功後,客戶端主動發起對伺服器端的Socket連接請求,伺服器端在指定埠監聽客戶端的連接請求,當連接成功後,伺服器端就可以獲取到客戶端的IP地址了

此處為了簡化操作,直接指定某台設備作為伺服器端(群主),即直接指定某台設備用來接收文件

因此,伺服器端要主動創建群組,並等待客戶端的連接

此處,使用 IntentService 在後台監聽客戶端的Socket連接請求,並通過輸入輸出流來傳輸文件。此處的代碼比較簡單,就只是在指定埠一直堵塞監聽客戶端的連接請求,獲取待傳輸的文件信息模型 FileTransfer ,之後就進行實際的數據傳輸

因為客戶端可能會多次發起連接請求,所以當此處文件傳輸完成後(不管成功或失敗),都需要重新 startService ,讓服務再次堵塞等待客戶端的連接請求

FileTransfer 包含三個欄位,MD5碼值用於校驗文件的完整性,fileLength 是為了用於計算文件的傳輸進度

為了將文件傳輸進度發布到外部界面,所以除了需要啟動Service外,界面還需要綁定Service,此處就需要用到一個更新文件傳輸狀態的介面

因此,需要將 progressChangListener 作為參數傳給 WifiServerService ,並在進度變化時更新進度對話框

四、客戶端加入群組並發起文件傳輸請求

文件發送界面 SendFileActivity 需要實現 DirectActionListener 介面

首先,需要先註冊P2P廣播,以便獲取周邊設備信息以及連接狀態

通過discoverPeers方法搜索周邊設備,回調函數用於通知方法是否調用成功

當搜索結束後,系統就會觸發WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION廣播,此時就可以調用requestPeers方法獲取設備列表信息,此處用 RecyclerView 展示列表,在 onPeersAvailable 方法刷新列表

之後,通過點擊事件選中群主(伺服器端)設備,通過connect方法請求與之進行連接

此處依然無法通過函數函數來判斷連接結果,需要依靠系統發出的WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION方法來獲取到連接結果,在此處可以通過requestConnectionInfo獲取到組連接信息,信息最後通過onConnectionInfoAvailable方法傳遞出來,在此可以判斷當前設備是否為群主,獲取群組IP地址

至此伺服器端和客戶端已經通過 Wifi P2P 連接在了一起,客戶端也獲取到了伺服器端的IP地址,在選取好待發送的文件後就可以主動發起對伺服器端的連接請求了

發起選取文件的方法

獲取選取的文件的實際路徑

文件的發送操作放到 AsyncTask 中處理,將伺服器端的IP地址作為參數傳進來,在正式發送文件前,先發送包含文件信息(文件名,文件大小,文件MD5碼)的信息模型 FileTransfer ,並在發送文件的過程中同時更新進度

五、校驗文件完整性

傳輸文件的完整性主要是通過計算文件的MD5碼值來保證了,在發送文件前,即在 WifiClientTask 的 doInBackground 方法中進行計算,將MD5碼值賦給 FileTransfer 模型,通過如下方法計算得到

因為客戶端會將 FileTransfer 傳給伺服器端,所以伺服器端在文件傳輸結束後,可以重新計算文件的MD5碼值,進行對比以判斷文件是否完整。

代碼地址:https://github.com/leavesC/WifiP2P

最後,歡迎大家加入我們的知識星球,第二期開期起航火熱進行中,已有近1000人加入學習:

歡迎大家儘早加入,這期是到2019年3月10日結束,所以越早加入越好,優惠活動結束,現入圈費用由79元提至89元,以後每滿100人費用增加10元~


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java和Android架構 的精彩文章:

Android系統將發生重磅變化!谷歌最新自主研發的新一代操作系統 Fuchsia OS 曝光:流暢度完勝蘋果iOS
深刻變革!移動端應用迎來WEB時代Google/Microsoft/Apple已全部支持PWA技術

TAG:Java和Android架構 |