蓝牙pbap协议源码解析

编程入门 行业动态 更新时间:2024-10-26 05:29:57

<a href=https://www.elefans.com/category/jswz/34/1768306.html style=蓝牙pbap协议源码解析"/>

蓝牙pbap协议源码解析

PBAP协议

使用场景:智能车载中同步联系人等信息

其实,不仅可以同步联系人,还可以同步通话记录等信息。

1.协议概述

协议代码路径: 

frameworks\opt\bluetooth\src\android\bluetooth\client\pbap这个包中

Jar包名称,android.bluetooth.client. pbap

所以进行开发时,在mk文件中需要添加这个包,

并且,在AndroidManifest文件中必须导入Obex库,<uses-libraryandroid:name="javax.obex" />

pbap这个包中文件如下,


使用pbap协议同步联系人/通话记录时的开发流程和其他的协议不一样,并且pbap协议只有客户端,没有服务端. BluetoothPbapClient是其客户端,在此先不看其客户端的方法。

2开发步骤

1) 构造BluetoothPbapClient对象,

2) 调用BluetoothPbapClient对象方法,处理对应的回调消息。

 

3详细开发过程

3.1构造BluetoothPbapClient

BluetoothPbapClient如何构造呢?源码有2个构造方法,其中一种如下 ,

public BluetoothPbapClient(BluetoothDevice device, Handler handler) { mClientHandler = handler; mSessionHandler = new SessionHandler(this); addSdp();mSession = new BluetoothPbapSession(device, mSessionHandler);}

从中可以看到,构造方法有2个参数, device当然是远程蓝牙设备了,这个很容易获取,

另外一个Handler对象,主要用于一些消息的回调,那就先新建一个Handler对象。

所以可以很简单的进行构造,

mPbapClient = new BluetoothPbapClient(device, mPbapHandler);

3.2方法以及回调处理

客户端BluetoothPbapClient的主要方法以及对应的回调消息如下,

方法

 

回调消息

setPhoneBookFolderRoot

刷选同步条件/

根目录/子目录/父目录

 

EVENT_SET_PHONE_BOOK_DONE

setPhoneBookFolderUp

setPhoneBookFolderDown

pullPhoneBookSize

电话本大小

EVENT_PULL_PHONE_BOOK_SIZE_DONE

pullVcardListingSize

文件数量

EVENT_PULL_VCARD_LISTING_SIZE_DONE

pullPhoneBook

同步电话本

EVENT_PULL_PHONE_BOOK_DONE

pullVcardListing

同步文件

EVENT_PULL_VCARD_LISTING_DONE

pullVcardEntry

同步单个文件

EVENT_PULL_VCARD_DONE

 

BluetoothPbapClient一些字符串定义如下,

public static final String ICH_PATH = "telecom/ich.vcf"; // 手机来电记录
public static final String OCH_PATH = "telecom/och.vcf"; // 手机去电记录
public static final String MCH_PATH = "telecom/mch.vcf";// 手机未接电话记录
public static final String CCH_PATH = "telecom/cch.vcf";  // 所有通话记录
public static final String PB_PATH = "telecom/pb.vcf";      // 手机联系人

对应的SIM卡上的通话记录以及联系人路径如下,

public static final String SIM_ICH_PATH = "SIM1/telecom/ich.vcf";
public static final String SIM_OCH_PATH = "SIM1/telecom/och.vcf";
public static final String SIM_MCH_PATH = "SIM1/telecom/mch.vcf";
public static final String SIM_CCH_PATH = "SIM1/telecom/cch.vcf";
public static final String SIM_PB_PATH = "SIM1/telecom/pb.vcf";

同步联系人的详细开发如下,

 设置路径,调用pullPhoneBook方法,

private String mDownloadSpinner = "telecom/pb.vcf";
mPbapClient. pullPhoneBook(mDownloadSpinner);

 回调处理

ArrayList<VCardEntry>pullPhoneBook; // 保存同步的联系人

private final Handler mPbapHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case BluetoothPbapClient.EVENT_PULL_PHONE_BOOK_DONE: pullPhoneBook = (ArrayList<VCardEntry>) msg.obj;break;}
};

到此, pullPhoneBook就保存了同步的联系人,后续就可以进行处理了。

同样的,也可以设置其他路径以方法同步通话记录等。

ArrayList<BluetoothPbapCard> pullVcardListing = null; // 保存同步文件
VCardEntry pullVcardEntry = null;  // 保存同步单个文件


 4流程图

同步的方法调用流程几乎是一模一样的,所以以pullPhoneBook方法为例,




流程图很简单,没有跨进程通信,只是单开一个线程同步联系人,每个联系人对应一个VCardEntry对象。VCardEntry对象在VCardEntryConstructor类中创建,在BluetoothPbapVcardList的内部类CardEntryHandler的onEntryCreated方法添加到名为mCards的ArrayList中。同步完之后, BluetoothPbapClient中的SessionHandler对象首先获取mCards,然后通过EVENT_PULL_PHONE_BOOK_DONE消息将mCards(VCardEntry数组)发出,因此在开发时处理该消息就可以获取同步的联系人。


5 VCardEntry简析

VCardEntry可以保存联系人/通话记录的各种信息,看枚举EntryLabel

public enum EntryLabel {

        NAME,

        PHONE,

        EMAIL,

        POSTAL_ADDRESS,

        ORGANIZATION,

        IM,

        PHOTO,

        WEBSITE,

        SIP,

        NICKNAME,

        NOTE,

        BIRTHDAY,

        ANNIVERSARY,

        ANDROID_CUSTOM

    }

 

    

每一个枚举对象都对应一个联系人信息,比如名字/电话号码,也对应一个VCardEntry的内部类,它们都继承内部接口EntryElement。

看下VCardParser_V21类parseOneVCard方法

private boolean parseOneVCard() throws IOException, VCardException {// reset for this entire vCard.mCurrentEncoding = DEFAULT_ENCODING;mCurrentCharset = DEFAULT_CHARSET;boolean allowGarbage = false;if (!readBeginVCard(allowGarbage)) {return false;}for (VCardInterpreter interpreter : mInterpreterList) {interpreter.onEntryStarted();}parseItems();for (VCardInterpreter interpreter : mInterpreterList) {interpreter.onEntryEnded();}return true;}

onEntryStarted最后会构造VCardEntry, parseItems会调用VCardEntry的addProperty方法完成各种信息的保存,最后调用onEntryEnded将所有VCardEntry对象打包到ArrayList中。

 

在这14个枚举中,并没有时间信息,即使是获取通话记录,也并没有时间的信息。如何同步时间信息呢?

查看PBAP协议,有一个这样的字段,X-IRMC-CALL-DATETIME,说明可以同步时间信息的。通过对VCardParserImpl_V21和VCardEntry的addProperty方法进行调试,发现X-IRMC-CALL-DATETIME参数是有输出的,只是VCardEntry中没有该枚举和对应的类而已。在VCardEntry中添加枚举和对应的内部类就可以实现同步时间的功能。

  1,,在枚举EntryLabel最后添加一项,

DATETIME

  2,, 添加对应的内部类

public static class DatetimeData implements EntryElement {private final String mDatetime;public DatetimeData(String datetime) {mDatetime = datetime;}@Overridepublic EntryLabel getEntryLabel() {return EntryLabel. DATETIME;}@Overridepublic boolean isEmpty() {return TextUtils.isEmpty(mDatetime);}@Overridepublic void constructInsertOperation(List<ContentProviderOperation>operationList, int backReferenceIndex) { }@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (!(obj instanceof DatetimeData)) {return false;}DatetimeData datetimeData = (DatetimeData) obj;return TextUtils.equals(mDatetime, datetimeData.mDatetime);}@Overridepublic int hashCode() {return mDatetime != null ? mDatetime.hashCode() : 0;}@Overridepublic String toString() {return "call datetime: " + mDatetime;}public String getCallDatetime() {return mDatetime;}}
 3,addProperty 方法
if(propertyName.equals(VCardConstants.PROPERTY_ DATETIME)) {mDatetimeData = new DatetimeData(propValue);  
}

4,,添加getter方法

public final String getCallDatetime() {return mCallDatetimeData != null ? mCallDatetimeData.mCallDatetime : null;}
在VCardConstants类中添加字符串,

public static final String PROPERTY_ DATETIME = "X-IRMC-CALL-DATETIME";

更多推荐

蓝牙pbap协议源码解析

本文发布于:2024-03-10 01:18:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726649.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:蓝牙   源码   协议   pbap

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!