安卓源码避坑指南5——获取通话记录或通讯录的数量为负值

通过蓝牙PBAP协议同步通讯录、通话记录时,想必对其数量大小也是很感兴趣的,因此一般的设计思路都是先获取到同步对象的总大小,然后再同步该对象的具体数据。

想法是美好的,然而现实却很魔幻。获取同步对象的总数量这块最近就遇到个奇怪问题——获取到的总数量为负值,今天就和大家一探究竟,详解此类问题。

测试环境:android-9车机系统(高通安卓源码)

测试步骤

  1. 车机蓝牙配对连接手机
  2. 车机同步通讯录、通话记录等(手机授权通讯录权限)

测试现象:获取到的通话记录数量为负值,由于应用内部逻辑,错误的负值不再同步该对象,通话记录为空。

What?怎么会获取到一个负值呢?带着疑问开始接下来的分析。

首先根据HCI层的交互,可以确定手机回复的数据是正确的,也就是说手机给的通话记录的size是个正数:

当我看到这个数量时,我心里萌生出这个想法:我的天,这哥们这么能打电话嘛…

而蓝牙服务层在接收到OBEX的回复消息后解析成了负值:

根据OBEX协议定义,同步对象的size大小使用两字节表示,所以41708的二进制表示法为:0b1010 0010 1110 1100,而 -23828的二进制表示法也为:0b1010 0010 1110 1100

对正负数在计算机中存储形式还不清楚的同学可以打电话给自己的大学计算机老师了(哈哈),这样就可以解释通话记录变为负值的原因了。java中的数据是有符号区分的,两个字节的short类型数据的范围为:-2^15 ~ 2^15-1。而 41708 这个数值很明显已经超出 short类型值的范围,因此溢出被解析成负值。

安卓源码中解析该数据的方法为:com.android.bluetooth.pbapclient.ObexAppParameters. getShort(),当byte型数组中存储的两字节数据超出short类型值的范围就会解析成异常值。

解决方案:获取到负值肯定不是我们所希望的,那如何才能正确获取某个同步对象的size大小值呢?java中没有提供相关方法来获取无符号的数值,但是我们可以通过数值操作间接获取到该数据对应的无符号值。

以上方法获取到的short类型值按位与上0xFFFF后赋值给到一个int类型的变量,则该int类型变量表示的值则为正确的short类型无符号值:

问题延伸

此类问题就是没有考虑到数值类型中有符号和无符号数据在值范围上的差异,同样地获取通讯录数量大小也是存在该风险的。最后的总结:数值由无符号转化为有符号时需注意数值是否有溢出风险

感兴趣的小伙伴欢迎私信留言一起讨论,源码避坑,永无止境,共同学习,一起进步!

request获取int类型的值_获取通话记录或通讯录的数量为负值相关推荐

  1. java获取radio选中的值_获取radio值

    使用jquery获取radio的值  使用jquery获取radio的值,最重要的是掌握jquery选择器的使用,在一个表单中我们通常是要获取被选中的那个radio项的值,所以要加checked来 ...

  2. java重div获取下拉框值_获取下拉框的value和值

    jsp: --请选择-- js: function labelCascade(){ $.ajax({ url:"admin/dianliang/gongyong/label/select/& ...

  3. 【iOS】Swift3 Swift2 String转int,从TextField里面获取Int类型的数值

    从Swift2开始,.toInt()方法就被移除了,现在转Int只需要这样写: String s = "123" let myInt = Int(s) 如果从TextField里面 ...

  4. 如何获取注解中的值_如何在运行时利用注解信息

    注解( annontation )是 Java 1.5 之后引入的一个为程序添加元数据的功能.注解本身并不是魔法,只是在代码里添加了描述代码自身的信息,至于如何理解和使用这些信息,则需要专门的解析代码 ...

  5. Redis 笔记(05)— hash 类型(设置获取单个hash值、判断hash键是否存在、设置获取多个hash值、获取所有hash的键、获取所有hash的值、删除hash指定键)

    Redis 的字典是无序字典.Redis 的字典的值只能是字符串,当 hash 移除了最后一个元素之后,该数据结构自动被删除,内存被回收. hash 结构也可以用来存储用户信息,不同于字符串一次性需要 ...

  6. es6 获取对象的所有值_前端开发必备 - ES6 新特性之 Set和Map数据结构

    往期回顾: 前端开发必备 - ES6 新特性之 let 和 const 命令 前端开发必备 - ES6 新特性之 变量的解构赋值 前端开发必备 - ES6 新特性之 字符串的拓展 前端开发必备 - E ...

  7. 【c++】如何获取int类型最大值以及float类型最大值

    原文链接 看下面的代码就知道了: #include <iostream> #include <limits.h>//里面有int类型的最大值和最小值 #include < ...

  8. html获取文本框的值,如何获取输入框的内容

    js如何获取input输入框中输入的值 直接使用.value属性即可获取输入框的内容. 详细的步骤如下: 首先获取输入框对应的DOM元素,如: var bt=document.getElementBy ...

  9. boolean类型默认值_「软帝学院」Java的基本数据类型

    Java的基本数据类型 Java的两大数据类型: · 内置数据类型 · 引用数据类型 内置数据类型 Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型 ...

最新文章

  1. slimphp中间件调用流程的理解
  2. ping 超时时间_华为交换机ping命令详解
  3. ns-3文件编译出错总结
  4. 一款猥琐的PHP后门分析
  5. python新手灰帽脚本练习---文件路径遍历收集
  6. 【Oracle】详解10053事件
  7. salt一键部署jdk
  8. 微软收购PhoneFactor以提高多因素身份认证应用程序的安全性
  9. 130242014062-黄凌逸-电商系统某功能模块“需求分析与设计实验课小结
  10. 谷歌强烈推荐!浏览器助手,让你的浏览器至少提升10个档次!
  11. 电动汽车仿真系列-电动汽车复合电源的建模与仿真研究
  12. 汽车传感器:自动驾驶“第一步”,新兴领域中国有望突围
  13. Java反序列化漏洞:在受限环境中从漏洞发现到获取反向Shell
  14. 【GIMP】免费开源图像处理软件,媲美PhotoShop(PS),入门式
  15. 消息称聊天宝团队解散 罗永浩已经退出股东行列
  16. 生也有涯而知也无涯,以有涯应无涯,殆矣
  17. java打印标签(机型TOSHIBA条码打印机B-EX4T)
  18. matlab模糊控制图怎么导出_matlab模糊控制工具箱的使用
  19. 深度优先搜索和深度优先搜索的区别
  20. 频次直方图、数据区间划分额分布密度——Note_6

热门文章

  1. sscanf高级用法级正则表达式
  2. mysql处理字符串的两个绝招:substring_index,concat
  3. MSSQL - 因为数据库正在使用,所以无法获得对数据库的独占访问权。
  4. 冲刺One之站立会议8 /2015-5-21
  5. 基于ThinkPHP的在线编辑器调用
  6. android 绘图之Canvas,Paint类
  7. SQL Server 2005 学习笔记系列文章
  8. MySQL显示ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)解决方法
  9. ssh 免密码登录(设置后仍需输密码的原因及解决方法)
  10. Netty 断线重连解决方案