『壹』 android-Ble藍牙開發Demo示例–掃描,連接,發送和接收數據,分包解包(附源碼)
萬物互聯的物聯網時代的已經來臨,ble藍牙開發在其中扮演著舉重若輕的角色。最近剛好閑一點,抽時間梳理下這塊的知識點。
涉及ble藍牙通訊的客戶端(開啟、掃描、連接、發送和接收數據、分包解包)和服務端(初始化廣播數據、開始廣播、配置Services、Server回調操作)整個環節以及一些常見的問題即踩過的一些坑。
比如
1、在Android不同版本或不同手機的適配問題,掃描不到藍牙設備
2、如何避免ble藍牙連接出現133錯誤?
3、單次寫的數據大小有20位元組限制,如何發送長數據
藍牙有傳統(經典)藍牙和低功耗藍牙BLE(Bluetooth Low Energy)之分,兩者的開發的API不一樣,本文主講Ble藍牙開發,傳統藍牙不展開,有需要的可以自行了解。
相對傳統藍牙,BLE低功耗藍牙,主要特點是快速搜索,快速連接,超低功耗保持連接和數據傳輸。
客戶端
服務端
Android4.3(API Level 18)開始引入BLE的核心功能並提供了相應的 API。應用程序通過這些 API 掃描藍牙設備、查詢 services、讀寫設備的 characteristics(屬性特徵)等操作。
BLE藍牙協議是GATT協議, BLE相關類不多, 全都位於android.bluetooth包和android.bluetooth.le包的幾個類:
android.bluetooth.
.BluetoothGattService 包含多個Characteristic(屬性特徵值), 含有唯一的UUID作為標識
.BluetoothGattCharacteristic 包含單個值和多個Descriptor, 含有唯一的UUID作為標識
.BluetoothGattDescriptor 對Characteristic進行描述, 含有唯一的UUID作為標識
.BluetoothGatt 客戶端相關
.BluetoothGattCallback 客戶端連接回調
.BluetoothGattServer 服務端相關
.BluetoothGattServerCallback 服務端連接回調
android.bluetooth.le.
.AdvertiseCallback 服務端的廣播回調
.AdvertiseData 服務端的廣播數據
.AdvertiseSettings 服務端的廣播設置
.BluetoothLeAdvertiser 服務端的廣播
.BluetoothLeScanner 客戶端掃描相關(Android5.0新增)
.ScanCallback 客戶端掃描回調
.ScanFilter 客戶端掃描過濾
.ScanRecord 客戶端掃描結果的廣播數據
.ScanResult 客戶端掃描結果
.ScanSettings 客戶端掃描設置
BLE設備分為兩種設備: 客戶端(也叫主機/中心設備/Central), 服務端(也叫從機/外圍設備/peripheral)
客戶端的核心類是 BluetoothGatt
服務端的核心類是 BluetoothGattServer 和 BluetoothLeAdvertiser
BLE數據的核心類是 BluetoothGattCharacteristic 和 BluetoothGattDescriptor
下面詳細講解下客戶端和服務端的開發步驟流程
安卓手機涉及藍牙許可權問題,藍牙開發需要在AndroidManifest.xml文件中添加許可權聲明:
在搜索設備之前需要詢問打開手機藍牙:
注意: BLE設備地址是動態變化(每隔一段時間都會變化),而經典藍牙設備是出廠就固定不變了!
通過掃描BLE設備,根據設備名稱區分出目標設備targetDevice,下一步實現與目標設備的連接,在連接設備之前要停止搜索藍牙;停止搜索一般需要一定的時間來完成,最好調用停止搜索函數之後加以100ms的延時,保證系統能夠完全停止搜索藍牙設備。停止搜索之後啟動連接過程;
BLE藍牙的連接方法相對簡單只需調用connectGatt方法;
參數說明
與設備建立連接之後與設備通信,整個通信過程都是在BluetoothGattCallback的非同步回調函數中完成;
BluetoothGattCallback中主要回調函數如下:
上述幾個回調函數是BLE開發中不可缺少的;
當調用targetdDevice.connectGatt(context, false, gattCallback)後系統會主動發起與BLE藍牙設備的連接,若成功連接到設備將回調onConnectionStateChange方法,其處理過程如下:
判斷newState == BluetoothGatt.STATE_CONNECTED表明此時已經成功連接到設備;
mBluetoothGatt.discoverServices();
掃描BLE設備服務是安卓系統中關於BLE藍牙開發的重要一步,一般在設備連接成功後調用,掃描到設備服務後回調onServicesDiscovered()函數,函數原型如下:
BLE藍牙開發主要有負責通信的BluetoothGattService完成的。當且稱為通信服務。通信服務通過硬體工程師提供的UUID獲取。獲取方式如下:
具體操作方式如下:
開啟監聽,即建立與設備的通信的首發數據通道,BLE開發中只有當客戶端成功開啟監聽後才能與服務端收發數據。開啟監聽的方式如下:
BLE單次寫的數據量大小是有限制的, 通常是20位元組 ,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20位元組,分兩種包,數據包和非數據包。對於數據包,頭兩個位元組表示包的序號,剩下的都填充數據。對於非數據包,主要是發送一些控制信息。
監聽成功後通過向 writeCharacteristic寫入數據實現與服務端的通信。寫入方式如下:
其中:value一般為Hex格式指令,其內容由設備通信的藍牙通信協議規定;
若寫入指令成功則回調BluetoothGattCallback中的onCharacteristicWrite()方法,說明將數據已經發送給下位機;
若發送的數據符合通信協議,則服務端會向客戶端回復相應的數據。發送的數據通過回調onCharacteristicChanged()方法獲取,其處理方式如下:
通過向服務端發送指令獲取服務端的回復數據,即可完成與設備的通信過程;
當與設備完成通信之後之後一定要斷開與設備的連接。調用以下方法斷開與設備的連接:
源碼上傳在CSDN上了,有需要的可以借鑒。
=====> Android藍牙Ble通訊Demo示例源碼–掃描,連接,發送和接收數據,分包解包
BLE單次寫的數據量大小是有限制的,通常是20位元組,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20位元組,分兩種包,數據包和非數據包。對於數據包,頭兩個位元組表示包的序號,剩下的都填充數據。對於非數據包,主要是發送一些控制信息。
總體流程如下:
1、定義通訊協議,如下(這里只是個舉例,可以根據項目需求擴展)
2、封裝通用發送數據介面(拆包)
該介面根據會發送數據內容按最大位元組數拆分(一般20位元組)放入隊列,拆分完後,依次從隊列里取出發送
3、封裝通用接收數據介面(組包)
該介面根據從接收的數據按協議里的定義解析數據長度判讀是否完整包,不是的話把每條消息累加起來
4、解析完整的數據包,進行業務邏輯處理
5、協議還可以引入加密解密,需要注意的選演算法參數的時候,加密後的長度最好跟原數據長度一致,這樣不會影響拆包組包
一般都是Android版本適配以及不同ROM機型(小米/紅米、華為/榮耀等)(EMUI、MIUI、ColorOS等)的許可權問題
藍牙開發中有很多問題,要靜下心分析問題,肯定可以解決的,一起加油;
『貳』 如何在 Android 手機上實現抓包
千鋒扣丁學堂Android開發為您解答:
tcpmp是最快捷方便的抓包方式,還可以加深對網路協議的理解。android下可以通過如下方式抓包:
1 Android上啟動tcpmp
Android設備可以把tcpmp的可執行文件上傳到android設備上,然後通過mac遠程登錄android設備運行tcpmp,前提是這台android設備必須已經root過。步驟如下:
下載android版本的tcpmp為android系統編譯的tcpmp版本。
通過adb將tcpmp上傳到android設備
通過adb push將tcpmp文件上傳到特定的目錄,這里我們選擇/sdcard/data目錄。
在android設備上運行tcpmp
通過adb shell登陸設備,並執行tcpmp,最後一步執行./tcpmp即可。
2. 分析tcpmp輸出
經過上面的步驟成功運行tcpmp之後,接下來就可以分析輸出的網路包內容了,iOS設備和Android設備的輸出是一致的。我們先來解析下幾個基本的格式:
圖中紅色方框內的部分是一個ip包的詳細記錄,類似的紀錄還有好幾條。這里我們著重分析第一條的各部分欄位含義。
14:37:41.615018 很簡單,是該包接收到的時間。
17.143.164.37.5223 是發送方的ip地址及埠號(5223是埠號)。
10.29.44.140.58036 是我android的ip地址及埠號。
Flags [P.]
是tcp包header部分的第14個位元組的P位。這個位元組所包含的幾個flag很重要,後面我會單獨詳細講解。這里P位表示接受方需要馬上將包push到應用層。
seq 1:54
tcp包的seq號,1是起始值,54結束值。tcp之所以被認為是流,是因為tcp包所攜帶的每一個位元組都有標號(seq號)。1:54表明總共有54個位元組被接受,其中一個位元組是三次握手階段所使用,所以一共發送的長度是53位元組。
ack 101 tcp包的ack號,ack 101表明seq號為100的位元組已被確認收到,下一個期望接收的seq號從101開始。
win 255 win表示的是tcp包發送方,作為接受方還可以接受的位元組數。這里win
255表明ip為17.143.164.37的主機還可以接受255個位元組。
options [nop,nop,…] options[…]表示的是該tcp包的options區域,nop是no
opertion的縮寫,沒什麼實際用途,主要是用做padding,因為options區域按協議規定必須是4位元組的倍數。
options[… TS val 2381386761] ts
val這個值是tcp包的時間戳,不過這個時間戳和設備的系統時間沒啥關系,剛開始是隨機值,後面隨著系統時鍾自增長。這個時間戳主要用處是seq序列號越界從0重新開始後,可以確認包的順序。
options[… ecr 427050796] ts ecr這個值主要用來計算RTT。比如A發送一個tcp包給B,A會在包里帶上TS
val,B收到之後在ack包里再把這個值原樣返回,A收到B的ack包之後再根據本地時鍾就可以計算出RTT了。這個值只在ack包里有效,非ack包ecr的值就為0.
length 53 這個length是應用層傳過來的數據大小,不包括tcp的header。這個值和我們上面分析的seq 1:54是一致的。
以上就是一個基本的tcp包結構,大家可以按照上面的分析再把其他幾個包理解下。我們在做應用的時候面對的更多是http協議,但對一個http請求是怎麼通過tcp/ip分解成一個個的packet,然後怎麼在網路上穩定可靠的傳輸,要有個基本的印象。下面我們再看下tcpmp更多的功能,這些功能都是基於對tcp/ip協議的理解,遇到不理解的建議多google下相關的技術概念。
3. tcpmp知識拓展
再繼續深入tcpmp之前,先貼上一張tcp header格式圖,常看常新。
[https://github.com/music4kid/music4kid.github.io/blob/master/images/tcpheader.png?raw=true](https://github.com/music4kid/music4kid.github.io/blob/master/images/tcpheader.png?raw=true)"
width="1056">
3.1 TCP Flags(tcp header第十四個位元組)
我們再仔細看下上面提到的flags概念,flags位於tcp
header的第十四個位元組,包含8個比特位,也就是上圖的CWR到FIN。這8個比特位都有特定的功能用途,分別是:CWR,ECE,URG,ACK,PSH,RST,SYN,FIN。
CWR ,ECE 兩個flag是用來配合做congestion
control的,一般情況下和應用層關系不大。發送方的包ECE(ECN-Echo)為0的時候表示出現了congestion,接收方回的包里CWR(Congestion
Window Reced)為1表明收到congestion信息並做了處理。我們重點看其他六個flag。
URG
URG代表Urgent,表明包的優先順序高,需要優先傳送對方並處理。像我們平時使用terminal的時候經常ctrl+c來結束某個任務,這種命令產生的網路數據包就需要urgent。
ACK
也就是我們所熟悉的ack包,用來告訴對方上一個數據包已經成功收到。不過一般不會為了ack單獨發送一個包,都是在下一個要發送的packet里設置ack位,這屬於tcp的優化機制,參見delayed
ack。
PSH Push我們上面解釋過,接收方接收到P位的flag包需要馬上將包交給應用層處理,一般我們在http
request的最後一個包里都能看到P位被設置。
RST Reset位,表明packet的發送方馬上就要斷開當前連接了。在http請求結束的時候一般可以看到一個數據包設置了RST位。
SYN
SYN位在發送建立連接請求的時候會設置,我們所熟悉的tcp三次握手就是syn和ack位的配合:syn->syn+ack->ack。
FIN
Finish位設置了就表示發送方沒有更多的數據要發送了,之後就要單向關閉連接了,接收方一般會回一個ack包。接收方再同理發送一個FIN就可以雙向關閉連接了。
這8個flag首字母分別是:C E U A P R S F。初看難以記憶,我腦洞了下,把它們組合成 supr
cafe,當然少了super少了個e,我可以將就下。我們在使用tcpmp的時候會經常看到這幾個flag,[S],[P],[R],[F],[.]。其他幾個都好理解,[.]特殊點,是個佔位符,沒有其他flag被設置的時候就顯示這個佔位符,一般表示ack。
3.2 tcpmp 更多使用參數
這部分我們來看下tcpmp常用的一些命令參數。文章最開始部分的tcpmp命令是這樣的:sudo tcpmp -i rvi0 -AAl。
-i rvi0 -AAl都是屬於參數部分。常見的有這些:
-i, 要監聽的網卡名稱,-i rvi0監聽虛擬網卡。不設置的時候默認監聽所有網卡流量。
-A, 用ASCII碼展示所截取的流量,一般用於網頁或者app里http請求。-AA可以獲取更多的信息。
-X,用ASCII碼和hex來展示包的內容,和上面的-A比較像。-XX可以展示更多的信息(比如link layer的header)。
-n,不解析hostname,tcpmp會優先暫時主機的名字。-nn則不展示主機名和埠名(比如443埠會被展示成https)。
-s,截取的包位元組長度,默認情況下tcpmp會展示96位元組的長度,要獲取完整的長度可以用-s0或者-s1600。
-c,只截取指定數目的包,然後退出。
-v,展示更多的有用信息,還可以用-vv -vvv增加信息的展示量。
src,指明ip包的發送方地址。
dst,指明ip包的接收方地址。
port,指明tcp包發送方或者接收方的埠號。
and,or,not,操作法,字面意思。
上面幾個是我個人比較常用的,更多的參數可以參考這個詳細文檔。有興趣的可以分析下面幾個例子練習下:
tcpmp 『tcp[13] & 16!=0』
tcpmp src port 80 and tcp
tcpmp -vv src and not dst port 23
tcpmp -nnvvS src 192.0.1.100 and dst port 443
4. 用tcpmp分析http完整請求
說了這么多,我們再來實戰下,看一個完整的http請求流程。sudo tcpmp -i rvi0 -AAl src 60.28.215.123 or
dst 60.28.215.123
列出了6個前面的packet,10.29.44.240是我android的ip地址,60.28.215.123是知乎server的ip地址,紅色方框內是android發出的packet,白色方框內是server發出的packet。packet1是android三次握手的第一個syn包,packet2是server
ack+syn的包,packet3是android ack的包。這3個packet之後tcp的三次握手就完成了。
packet4是android發出的http
request。長度只有240個位元組,所以一個packet就發過去了,當然還設置了flags的P位,request需要馬上被應用層處理。包裡面出現了spdy,點贊。
packet5是server ack剛收到的包,長度位0,所以這僅僅是一個ack包。
packet6是server返回http的response了,1388個位元組。packet5和packet6都ack了seq為241的包,當然是為了增加ack的成功率。
中間還有好幾個packet就不仔細分析了,最後再看下請求完成的最後幾個包:
最後兩個packet比較簡單,android發送個FIN+ACK的包就斷開連接了,server直接發送了一個RST包後也斷開連接了。
『叄』 安卓APK大型游戲的數據包要放在哪裡
在Android系統中,數據包通常會被存放在幾個特定的目錄下,以確保游戲能夠順利運行。大部分游戲的數據包會存儲在Android/data或Android/obb目錄中。部分游戲則可能存儲在Gameloft/games目錄下。這些路徑的選擇依據是游戲本身的特性與需求。
出於節省存儲空間的考慮,許多游戲開發商會選擇根據用戶的設備類型推送不同版本的數據包,而不是統一推送一個較大體積的通用版。這意味著玩家需要下載與自己設備匹配的數據包,才能保證游戲的正常運行。
為了給玩家提供更加便捷的游戲體驗,當樂網通常會預先設定好數據包的路徑,以減少玩家在下載和安裝過程中遇到的麻煩。此外,當樂游戲中心的手機客戶端也提供了一鍵安裝數據包游戲的功能,極大地方便了用戶。
使用當樂游戲中心,玩家無需費心查找數據包的具體位置,也不必擔心因路徑錯誤導致的游戲無法啟動等問題。整個過程簡單快捷,提高了游戲安裝的效率。
當樂網致力於為玩家提供更加便捷、愉快的游戲體驗。我們希望每位玩家都能享受到流暢的游戲過程,祝您游戲愉快。