一. 簡介:
此功能具體使用的是bluetoothV2.1之后的Phone Book Access Profile功能,簡稱PBAP .目前MTK Android中只實現了server端的功能,並沒有實現client.所以該文檔簡略介紹了如何開發一個簡易client.並在最后給出一個測試用的demo.下面就按照客戶端的開發流程來說明.
二. 前提設置:
本處介紹執行PBAP之前的藍牙需要的一些操作.其包括開啟和搜索.
首先在manifest中加入權限
<uses-permissionandroid:name="android.permission.BLUETOOTH"/> <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/> |
判斷是否開啟
private BluetoothAdaptermBluetoothAdapter; if (null ==mBluetoothAdapter) { mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } if (!mBluetoothAdapter.isEnabled()) { mStatus = CLOSE; } else { mStatus = OPEN; } |
如果未開啟,則執行開啟
Intent startBluetoothIntent = new Intent( BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(startBluetoothIntent, 1001 ); //1001 = BT OPEN |
執行完開啟后在onActivityResult中取收取反饋
protected void onActivityResult(int requestCode,int resultCode, Intent data) { if (requestCode ==1001) { //1001 = BT OPEN if (resultCode ==RESULT_OK) { mBtStatus.setCurrStatus(BtStatus.OPEN); } else { //在打開時的dialog中選擇取消也會反饋到這里 mBtStatus.setCurrStatus(BtStatus.OPEN_FAILED); } } } |
反饋中接受為OK的話,下一步可以開始搜索附近藍牙設備
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter.startDiscovery();
|
搜索的時候需要監聽下面幾個action
IntentFilter iFilter = new IntentFilter(); iFilter.addAction(BluetoothDevice.ACTION_FOUND); iFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
|
在定義的BroadCast中存儲搜索到的BLUETOOTH_DEVICE
BluetoothDevice bluetoothDevice = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); |
搜索的時候可以取消,相關函數為
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter. cancelDiscovery ();
|
三. 藍牙的配對連接
//此處的UUID是協議中規定的.這樣才能訪問server端的pbap服務. //在spec中未看到.但是查閱了藍牙的UUID相關中有發現這個條目 //同0X1103 MY_UUID = UUID.fromString("0000112f-0000-1000-8000-00805f9b34fb"); //api中提供的安全連接方法 BluetoothSocket socket = device.createRfcommSocketToServiceRecord(MY_UUID); //連接函數.此為broken方法,需要放入thread中取處理 socket.connect(); |
SPEC中描述2個設備中需要GAP認證建立安全連接.本處使用SDK中提供的
|
上面的步驟操作完之后,服務端和客戶端都會彈出一個配對對話框.在雙方都配對成功后.服務端又會彈出一個是否允許對方獲取聯系人的確認.在對方確認后.socket.connect才執行完成.
上面整了這么多.其實都是前期的必須操作.至此2台手機連接上了.並建立了PBAP連接.
四. PhoneBook DownLoad Feature
下面開始操作server端電話本下載功能.在spec中的功能流程圖如下
下面分開說明這些步驟:
1. PCE建立和PSE的連接
先聲明此處的連接跟前一節說的連接是兩回事.前一節是2台機器建立藍牙連接
此處為OBEX的連接.
client請求數據包格式
Client request 解釋:
80 op
001f 整個數據包長度
10 OBEX版本,始終10
00 flags始終00
2000 數據包的最大長度2k
下面7-n為header關於header請查看obex spec
46 target
0013 target header的長度
796135f0f0c511d809660800200c9a66 此處不知道哪里來的.但就是這個
c3 length
0000f483 length值
現在發現connect的時候.這串字符串是不需要變得.肯定是這個
server反饋數據包格式
Server response 解釋:
這個是隨意找了一台手機做的測試結果.不過一般都相差不大.關鍵點connect id
a0 response code(只有a0為成功,其他都為各式各樣的錯誤)
001f 長度
10 obex 版本
00 flags
4bc8 最大數據包長度
下面都是header信息.關於header請查看obex spec
Cb connect id(關鍵.很重要)
00000007connect id value(這個值需要存儲下來.下面會用的到)
4a who
0013 who的長度
796135f0f0c511d809660800200c9a660000000 who的值(跟上面的target是一樣的)
判斷完response code為a0 就可以操作下一步了.
2. PCE下載聯系人
PCE下載聯系人需要用到的是GET方法.
在OBEX中GET方法如下定義
在PBAP SPEC中定義了如下的要求
按照上圖描述.數據組織如下
83 get(也可以為03)
004f 整個數據包的長度.最后手動計算得出
Cb connect id
00000007 此處就為上面connect方法執行完成之后得到的數據.
01 name
0021 name的長度
00740065006c00650063006f006d002f00700062002e0076006300660000
上面為telecom/pb.vcf的unicode碼.結尾必須要0000收尾.對於name在obex中定義必須要用unicode來處理.這個字串表示取到對方手機存儲中所有的聯系人.
42 type
0012 type的長度
782d62742f70686f6e65626f6f6b00 為x-bt/phonebook 結尾必須用00.此處
4c app params
0014 app params 的長度
06 此處為pbap自定義,表示vcardfilter
08 8位
0000000000000000 64位掩碼.需要的話請看spec.全為0,則返回所有的
07 vcard 版本
01 長度
01 01= 3.1 00 = 2.0
04 maxlistcount 取多少個
02 長度
Ffff ffff表示取所有的.
此處的例子說明的是取對方聯系人中手機內純中所有的.
maxlistcount的參數並沒有做測試.也不知道設置了在此處是否有用.
vcard的版本,服務端是會同時定義好2.0和3.1的vcardbuilder的,這個是協議中要求的.所有對於客戶端具體我們想要用那個,視我們用那個vard praser來決定.
Filter其實很有用.規定了我們取哪些數據回來.畢竟如果服務端的聯系人都有頭像之類的.我們要是全取回來.要考慮下速度的問題了
ListStartOffset,改例子取全部.所有這個參數都沒傳過去.默認就為0.
server反饋數據包格式
此處沒有存數據.暫時沒有例子.分析也同上
Response code必須要為a0才能繼續解析
Header中的解析到body或者end of body的話.則根據length,把這段buffer存儲下來.直接保存到vcf文件中就行了.當然.如果code中實現了vcard praser,則可以直接去解析並載入到聯系人數據庫中.
順便說明下:對於PBAP.MTK不支持calllog的處理.其他的spec中有的都支持.
3. 虛線處表示可此處循環.
此處不做詳細解釋.可以查看pbap spec中虛擬文件夾這一塊.此處的功能可以單獨下載server端1個或者幾個聯系人.
要實現此處功能.最好也先了解下phonebook browser的功能.
4. PCE終端跟PSE的連接
調用OBEX的disconnect功能就可以了.目前代碼未實現
五. 目前總結
簡易完成了demo.保存至T卡的vcf可以正常導入的本地聯系人.但是代碼流程全是按照一些正常的操作來走的.后續需要把需要的錯誤處理全部加上去.
參考資料:
使用 JSR-82 API 實現 OBEX 圖像傳輸
http://419443161-qq-com.iteye.com/blog/544299
Android手機的PIM同步技術的研究與實現
http://cdmd.cnki.com.cn/Article/CDMD-10614-1012470693.htm
PBAP協議中文精簡版
http://www.docin.com/p-204262132.html