PBAP
Phone Book Access Profile 定义了两部设备间传输通讯录的协议。主要是为车载终端的 Hands-free 使用场景设计,可以将移动设备上的通讯录同步到车载设备上。也可用于客户端请求访问储存在服务端的通讯录。
- PPS object: Shows the profile used for a connected device
- PBAP 协议相关
OBEX
OBject EXchange 的缩写。OBEX 是一个在设备间交换二进制对象的协议。
它在设计上和 HTTP 协议相似,为 client 和 server 提供可靠连接来传输数据。
主要区别有:
- HTTP 通常在 TCP/IP 连接下使用。OBEX 也可以,不过更常见是用于红外和蓝牙这些设备的连接上,或者 USB 设备
- HTTP 的传输内容为可读文本,OBEX 是二进制,更利于在设备资源有限的情况下解析
- HTTP 的每个请求之间是无关联的,而 OBEX 的每个请求可能影响后续请求
For Android
在 Android 源码中已经有 PBAP 协议实现,不过处于 hide 状态,简单点可以把源码拷贝到自己的包名下使用。
相关代码:
使用方式:
connect
1
2
3
4
5// 首先和普通蓝牙一样通过适配器获取设备,然后构造 BluetoothPbapClient 对象
private fun getPBAPClient(address: String) = BluetoothPbapClient(btAdapter?.getRemoteDevice(address), handler)
// 尝试链接
pbapClient = getPBAPClient(address)
pbapClient?.connect()handler 用来处理整个过程中的消息(BluetoothPbapClient#EVENT_*), 和已有逻辑使用同一个 handler 时需要注意不要和自己的消息冲突, 最好单独创建一个 handler .
最终会调用以下函数:
1
2
3
4
5
6
7
8
9
10// android.bluetooth.client.pbap.BluetoothPbapSession$RfcommConnectThread::run
// 建立一个连接
mSocket = mDevice.createRfcommSocketToServiceRecord(
UUID.fromString(PBAP_UUID));
mSocket.connect();
// 初始化 OBEX
BluetoothPbapObexTransport transport;
transport = new BluetoothPbapObexTransport(mSocket);
// 发送连接成功 MSG
mSessionHandler.obtainMessage(RFCOMM_CONNECTED, transport).sendToTarget();Pull
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 拉取数据
pbapClient?.pullPhoneBook(BluetoothPbapClient.PB_PATH)
/**
* Pulls complete phone book.
*
* @param pbName absolute path to the phone book
* @param filter bit mask which indicates which fields of the vCard hall be
* included in each entry of the resulting list
* @param format vCard format of entries in the resulting list
* @param maxListCount limits number of entries in the response
* @param listStartOffset offset to the first entry of the list that would
* be returned
* @return <code>true</code> if request has been sent successfully;
* <code>false</code> otherwise; upon completion PCE sends
* {@link #EVENT_PULL_PHONE_BOOK_DONE} or
* {@link #EVENT_PULL_PHONE_BOOK_ERROR} in case of failure
*/
public boolean pullPhoneBook(String pbName, long filter,
byte format, int maxListCount,int listStartOffset)- pbName: 表示想要拉取的数据, 包括并不限于通讯录, 通话记录, 未接来电, etc(详见 BluetoothPbapClient#*_PATH)
- Filter: 可以过滤掉 VCard 中不需要的字段(
0x07
-> NameAndNumberOnly)
最终会通过 BluetoothPbapClient.EVENT_PULL_PHONE_BOOK_DONE 消息的 msg.obj
字段把一个 ArrayList<VCardEntry>
对象传递到 handler.
测试结果
4.4.4 设备连接 7.1 手机: 成功 (手机需点同意访问通讯录)
7.1 手机连接 7.1 手机: 成功 (两部手机都要点同意访问通讯录)