【android bluetooth 协议分析 18】【PBAP详解 2】【车机为何不显示电话号码为空的联系人信息】

一、问题描述

在苹果手机中, 会将 只有名字,没有电话号码的 vcard 传到 车机侧。 但是应用侧确显示不出来。针对这个问题,我们深入探讨一下,究竟是谁把他给过滤掉了。

下面的log 是从 btsnoop 中导出的。

c 复制代码
BEGIN:VCARD
VERSION:3.0
FN:空号测试
N:空号测试
TEL:
END:VCARD


BEGIN:VCARD
VERSION:3.0
FN:Konghao 
N:Konghao 
TEL:
END:VCARD

备注:

  • 但是用其他手机, 例如 IQOO Nevo 3E 上述 vcard 并不会 通过蓝牙 传递到 车机侧, 只有 苹果手机会传。

二、源码回溯

当车机解析手机传递过来的 vcard 时, 将触发 VCardEntry.java::addProperty. 调用流程可以参考 【android bluetooth 协议分析 18】【PBAP详解 1】【为何我们的通话记录中会出现1-521-8xx-1x9x】 这里不再重复。

  • android/frameworks/opt/vcard/java/com/android/vcard/VCardEntry.java
c 复制代码
    public void addProperty(final VCardProperty property) {
        final String propertyName = property.getName();
        final Map<String, Collection<String>> paramMap = property.getParameterMap();
        final List<String> propertyValueList = property.getValueList();
        byte[] propertyBytes = property.getByteValue();

        if ((propertyValueList == null || propertyValueList.size() == 0)
                && propertyBytes == null) {
            return;
        }
        final String propValue = (propertyValueList != null
                ? listToString(propertyValueList).trim()
                : null);

        if (propertyName.equals(VCardConstants.PROPERTY_VERSION)) {
            // vCard version. Ignore this.
        } else if (propertyName.equals(VCardConstants.PROPERTY_FN)) {
			...
        } else if (propertyName.equals(VCardConstants.PROPERTY_NAME)) {
			...
        } else if (propertyName.equals(VCardConstants.PROPERTY_N)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_SORT_STRING)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_NICKNAME)
                || propertyName.equals(VCardConstants.ImportOnly.PROPERTY_X_NICKNAME)) {
           ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_SOUND)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_ADR)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_EMAIL)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_ORG)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_TITLE)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_ROLE)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_PHOTO)
                || propertyName.equals(VCardConstants.PROPERTY_LOGO)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_TEL)) {
            String phoneNumber = null;
            boolean isSip = false;
            if (VCardConfig.isVersion40(mVCardType)) {
				...
            } else {
                phoneNumber = propValue;
            }

            if (isSip) {
				...
            } else {
                if (propValue.length() == 0) {
                    return; // 这里当 TEL 标签 空时,直接返回了。 这里直接将 TEL 为空的联系人给过滤掉了。
                }

                final Collection<String> typeCollection = paramMap.get(VCardConstants.PARAM_TYPE);
                final Object typeObject = VCardUtils.getPhoneTypeFromStrings(typeCollection,
                        phoneNumber);
                final int type;
                final String label;
                if (typeObject instanceof Integer) {
                    type = (Integer) typeObject;
                    label = null;
                } else {
                    type = Phone.TYPE_CUSTOM;
                    label = typeObject.toString();
                }

                final boolean isPrimary;
                if (typeCollection != null &&
                        typeCollection.contains(VCardConstants.PARAM_TYPE_PREF)) {
                    isPrimary = true;
                } else {
                    isPrimary = false;
                }
                addPhone(type, phoneNumber, label, isPrimary);
            }
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SKYPE_PSTNNUMBER)) {
            ...
        } else if (sImMap.containsKey(propertyName)) {
           ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_NOTE)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_URL)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_BDAY)) {
            mBirthday = new BirthdayData(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_ANNIVERSARY)) {
            mAnniversary = new AnniversaryData(propValue);
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
            mNameData.mPhoneticGiven = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
            mNameData.mPhoneticMiddle = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME)) {
            mNameData.mPhoneticFamily = propValue;
        } else if (propertyName.equals(VCardConstants.PROPERTY_IMPP)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_SIP)) {
            ...
        } else if (propertyName.equals(VCardConstants.PROPERTY_X_ANDROID_CUSTOM)) {
            ...
        } else if (propertyName.toUpperCase().startsWith("X-")) {
            ...
        } else {
        }
        // Be careful when adding some logic here, as some blocks above may use "return".
    }

return 注释掉后, 电话号码为空的联系人,也可以正常在车机进行显示了。

相关推荐
Dovis(誓平步青云)14 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
alexhilton15 小时前
让架构边界变成可执行的测试
android·kotlin·android jetpack
hai_android16 小时前
SendChannel 与 ReceiveChannel 通信机制
android
数据治理自习室18 小时前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
爱笑鱼19 小时前
Android 系统启动机制(五):system_server 是 init 启动的,还是 Zygote fork 出来的?
android
智购科技无人售货机工厂20 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
开开心心就好20 小时前
电子教鞭工具支持画框写字插图片功能齐全
android·开发语言·前端·javascript·人工智能·pdf·html
Dovis(誓平步青云)20 小时前
拍视频前先把镜头想清楚:做一个分镜取景辅助器
android·java·服务器·javascript·人工智能
峥嵘life21 小时前
Android16 系统 APEX 模块说明
android·大数据·开发语言
2601_962065491 天前
PHP For 循环
android·java·php