【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 注释掉后, 电话号码为空的联系人,也可以正常在车机进行显示了。

相关推荐
Doro再努力5 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Daniel李华6 小时前
echarts使用案例
android·javascript·echarts
做人不要太理性7 小时前
CANN Runtime 运行时组件深度解析:任务调度机制、存储管理策略与维测体系构建逻辑
android·运维·魔珐星云
我命由我123457 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
朗迹 - 张伟8 小时前
Tauri2 导出 Android 详细教程
android
lpruoyu8 小时前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
独自破碎E9 小时前
【BISHI15】小红的夹吃棋
android·java·开发语言
李堇12 小时前
android滚动列表VerticalRollingTextView
android·java
lxysbly13 小时前
n64模拟器安卓版带金手指2026
android
游戏开发爱好者816 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview