android 藍牙 pbap 獲取通話時間
之前,我們利用 pbap 協(xié)議獲取到了用戶的通訊錄缓熟。那自然而然產(chǎn)生了衍生需求:能否獲取通話記錄今艺?包括打電話記錄(DIALED)缩筛、接電話記錄(RECEIVED)、未接電話記錄(MISSED)锌仅?
答案是肯定的章钾。類比獲取通訊錄的方式,我們可以通過修改client.pullPhoneBook(BluetoothPbapClient.PB_PATH);
中的PB_PATH
參數(shù)热芹,來獲取其他的信息贱傀。比如:
/**
* Path to local incoming calls history object
*/
public static final String ICH_PATH = "telecom/ich.vcf";
/**
* Path to local outgoing calls history object
*/
public static final String OCH_PATH = "telecom/och.vcf";
/**
* Path to local missed calls history object
*/
public static final String MCH_PATH = "telecom/mch.vcf";
/**
* Path to local combined calls history object
*/
public static final String CCH_PATH = "telecom/cch.vcf";
/**
* Path to local main phone book object
*/
public static final String PB_PATH = "telecom/pb.vcf";
但是,在替換PB_PATH
為其他的各種 PATH 之后传透,我們發(fā)現(xiàn)獲取的信息不完全异吻。我們從控制臺中輸出的信息只有按時間順序倒敘排列的一堆聯(lián)系人信息(其實是VCardEntry
對象,控制臺輸出的時候調(diào)用了VCardEntry#toString()
)巫俺。每一個聯(lián)系人信息如下:
[[
hash: 427457895
NAME: [family: nameOfThePerson, given: null, middle: null, prefix: null, suffix: null]
PHONE: [type: 2, data: 1-111-111-1111, label: null, isPrimary: false]
]]
問題來了株搔,怎么沒有時間信息剖淀?對于通話記錄而言,時間信息還是比較重要的纤房。那么纵隔,是 pbap 協(xié)議就不會給我們返回時間?還是我們解析時間數(shù)據(jù)的時候出了錯誤炮姨?或者是手機廠商在實現(xiàn) pbap server 端的時候偷工減料了呢捌刮?
首先,先去藍牙 pbap 協(xié)議中查看是否有通話記錄對應(yīng)的描述:
3.1.4.1 Call History extension
The time of each call found in och, ich, mch and cch folder, can be shown using the
IrMC [13] defined X-IRMC-CALL-DATETIME property that extends the vCard
specification. This attribute can be used in combination with three newly created
property parameters:
? MISSED
? RECEIVED
? DIALED
These are used to indicate the nature of the call that is time-stamped with X-IRMCCALL-DATETIME.
For instance, a call that was missed on March 20th, 2005 at 10 am would be stamped:
X-IRMC-CALL-DATETIME;MISSED:20050320T100000
It is strongly recommended to use this property parameter whenever possible. They are
especially useful in vCards that are retrieved from the cch folder ( see Section 3.1.2 ).
Note that it is legal to use this property with no data; i.e,
X-IRMC-CALL-DATETIME;MISSED:
看來舒岸,關(guān)于通話記錄糊啡,PBAP 協(xié)議是有所規(guī)定的。所以吁津,問題可能出在手機廠商的 pbap server 端或者是出在我們解析數(shù)據(jù)的時候棚蓄。通過對VCardParserImp_V21
進行深層次的調(diào)試,我們發(fā)現(xiàn)碍脏,X-IRMC-CALL-DATETIME
參數(shù)是有輸出的梭依。那就說明是手機端的 pbap server 是沒有問題的。問題出在我們的 pbap client 上典尾。更具體的定位一下役拴,是我們解析這個參數(shù)的時候出了問題,或者是根據(jù)解析出的參數(shù)構(gòu)造VCardEntry
的時候出了問題钾埂。
繼續(xù)調(diào)試河闰,在 VCardEntry#addProperty(VCardProperty property)
函數(shù)中,可以輸出 property
并且也是有 X-IRMC-CALL-DATETIME
對應(yīng)的數(shù)據(jù)的褥紫。那么姜性,最終鎖定了問題:我們構(gòu)造 VCardEntry
的時候,沒有把 X-IRMC-CALL-DATETIME
加進來髓考。更本質(zhì)的原因是部念,android sdk 23 的相關(guān)源碼中,沒有定義 X-IRMC-CALL-DATETIME
相關(guān)的字段氨菇。
找到了問題所在儡炼,改的時候就非常好改了。
首先查蓉,在 VCardConstants.java 中添加
public static final String PROPERTY_X_IRMC_CALL_DATETIME = "X-IRMC-CALL-DATETIME"; // added
然后乌询,在 VCardEntry.java 中添加:
public enum EntryLabel {
NAME,
PHONE,
EMAIL,
POSTAL_ADDRESS,
ORGANIZATION,
IM,
PHOTO,
WEBSITE,
SIP,
NICKNAME,
NOTE,
BIRTHDAY,
ANNIVERSARY,
ANDROID_CUSTOM,
CALL_DATETIME // added
}
然后,添加 CALL_DATETIME
對應(yīng)的類:
public static class CallDatetimeData implements EntryElement {
private final String mCallDatetime;
public CallDatetimeData(String datetime) {
mCallDatetime = datetime;
}
/** start implementing EntryElement */
@Override
public EntryLabel getEntryLabel() {
return EntryLabel.CALL_DATETIME;
}
@Override
public boolean isEmpty() {
return TextUtils.isEmpty(mCallDatetime);
}
@Override
public void constructInsertOperation(List<ContentProviderOperation> operationList, int backReferenceIndex) {
// 我沒看懂這個函數(shù)要干嘛豌研,時間有限妹田,先不改了竣灌。
}
/** end implementing EntryElement */
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CallDatetimeData)) {
return false;
}
CallDatetimeData datetimeData = (CallDatetimeData) obj;
return TextUtils.equals(mCallDatetime, datetimeData.mCallDatetime);
}
@Override
public int hashCode() {
return mCallDatetime != null ? mCallDatetime.hashCode() : 0;
}
@Override
public String toString() {
return "call datetime: " + mCallDatetime;
}
public String getCallDatetime() {
return mCallDatetime;
}
}
最后是在構(gòu)造 VCardEntry 對象的時候,將這個字段添加進來:
在 VCardEntry#addProperty()
中秆麸,添加:
if (propertyName.equals(VCardConstants.PROPERTY_X_IRMC_CALL_DATETIME)) {
mCallDatetimeData = new CallDatetimeData(propValue);
}
然后在 VCardEntry 中添加一個 getter 就完事了:
public final String getCallDatetime() {
return mCallDatetimeData != null ? mCallDatetimeData.mCallDatetime : null;
}