李忠丞 沈阳大学学士,腾讯优测产品支撑组组长;2011年加入腾讯,专一移动终端开发,前后参与过腾讯微博研发以及手机QQ浏览器、Qzone、魅拍等产品的机型适配工做。android
快捷方式虽然看起来只是一个很小的功能点,可是他涉及到的机型适配问题不少。数据库
快捷方式建立代码:编程
ntent addShortCut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT"); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); // 不容许重复建立 addShortCut.putExtra("duplicate", false); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent); sendBroadcast(addShortCut);
1 没法建立快捷方式浏览器
愈来愈多的手机厂商取消了快捷方式的概念,致使咱们没法经过代码建立一个咱们须要的快捷方式,根据咱们所掌握的数据显示,这样的手机约占 13%。markdown
2 重复建立快捷方式app
一般状况下,咱们是不但愿本身的快捷方式被重复建立:布局
使用 addShortCut.putExtra(“duplicate”, false);方法就能达到目的,可是市面上的手机至少有 8%的手机即便设置了 DUPLICATE 为 FALSE 仍是能够重复建立快捷方式的。spa
表明手机品牌为:华为 中兴 HTCcode
Android Launcher 源码:orm
2.1 重复建立快捷方式的解决方案 V1.X
咱们最先使用的解决快捷方式重复建立的方法是:在建立快捷方式前先执行删除操做,这种方式其实很聪明,由于即便是在快捷方式不存在的状况下执行删除操做也不会有任何异常,这样看来问题解决地过轻松了,可是遗憾的是删除快捷方式一样存在适配问题,咱们掌握的数据显示大约 21%的手机没法正常删除快捷方式。
另一种方法是:自行保存快捷方式的建立记录,经过一个字段来记录快捷方式是否已经建立过了,以此来决定是否建立新的快捷方式,这种作法也是由于出现快捷方式没法删除状况后对解决方案进行了一个小的升级,虽然能够解决问题,可是若是程序被清除了数据,那么一切都乱了,仍是没法完全的规避重复的问题。
2.2 重复建立快捷方式的解决方案 V2.X
遇到难解的问题仍是看看源码吧,Android 的 Launcher 源码在建立快捷方式的时候不只会判断 duplicate 的值,还会在数据库中查询一下将要被建立的快捷方式是否已经存在,咱们也照作就 OK 了。
咱们注意到,查询数据库的时候访问地址URI 是一个很重要的因素,问题是数据库的URI比较多,Android 标准的URI 就有3 个:
2.2 版本之前的URI 是:content://com.android.launcher.settings/favorites?notify=true
2.2~4.3 版本的URI 是:content://com.android.launcher2.settings/favorites?notify=true
4.4 版本以上的目前都是:content://com.android.launcher3.settings/favorites?notify=true
不只仅Android 本身的Launcher 数据库地址众多,厂商本身定义的地址就更加丰富多彩,如OPPO R827T 的访问URI 为:content://com.oppo.launcher.settings /favorites?notify=true
HTC Z715e 的访问地址为:
content://com.htc.launcher.settings/favorites?notify=true
远远不止这些,还有不可胜数的第三方Launcher 应用,不少开发者也会修改数据库访问地址,目前仅咱们掌握的不一样访问地址就有多达40 种左右。
经过权限查询URI:
经过数据库的读写权限来查询对应的URI 相信你们也不陌生,感受上像是找到了终极的解决方案,且看下去…
问题一:若是使用完整的权限进行查询—权限众多,咱们目前掌握的超过 50 种。
问题二:若是使用不完整的权限进行查询(READ_SETTINGS)对应关系复杂,大约有 32%的手机会对应两个以上的 URI。
例如:
GT-I8262D:
authority:com.sec.android.app.launcher.settings
ReadPermission:com.android.launcher.permission.READ_SETTINGS
authority:com.sec.android.app.launcher.settings.id
ReadPermission:com.android.launcher.permission.READ_SETTINGSLenovo A278t:
authority:com.aspire.mm.Settings ReadPermission:com.aspire.mm.permission.READ_SETTINGS
authority:com.huaqin.launcherEx.settings
ReadPermission:com.huaqin.launcherEx.permission.READ_SETTINGS
authority:com.huaqin.thememgr.Settings
ReadPermission:com.huaqin.thememgr.permission.READ_SETTINGS
1 Intent 调用手机内相机程序
若是咱们设置了照片的存储路径,那么极可能会遇到一下三种问题:
问题一:onActivityResult 方法中的data 返回为空(数据代表,93%的机型的data 将会是Null,因此若是咱们指定了路径,就不要使用data 来获取照片,起码在使用前要作空判断)
问题二:照片没法存储
若是自定义存储路径是/mnt/sdcard/lowry/,而手机SD 卡下在拍照前没有名为lowry 的文件夹,那么部分手机拍照后图片不会保存,致使咱们没法得到照片,大多数手机的相机遇到文件夹不存在的状况都会本身建立出不存在的文件夹,而个别手机却不会建立,其表明机型为:三星I825八、华为H30-T00、红米等。解决的方法就是在指定存储路径前先判断路径中的文件夹是否都存在,不存在先建立再调用相机。
问题三:照片能够存储,可是名字不对
file:///mnt/sdcard/123 1.jpg,因为Uri 的fromFile 方法会将路径中的空格用“%20”取代。其实对于大多数的手机这都不算事,手机在解析存储路径的时候都会将“%20”替换为空格,这样实际上最终的照片名字仍是咱们当初指定的名字:123 1.jpg,遗憾的是个别手机(如酷派7260)系统自带的相机没有将“%20”读成空格,拍照后的照片的名字是123%201.jpg,咱们用路径“file:///mnt/sdcard/123 1.jpg”能找到照片才怪!!
总结:
(1)使用 onActivityResult 中的 intent(data)前要作空判断。
(2)指定拍照路径时,先检查路径中的文件夹是否都存在,不存在时先建立文件夹再调用相机拍照。
(3)指定拍照存储路径时,照片的命名中不要包含空格等特殊符号。
2 经过 Camera 的 open 方法调用手机摄像头
2.1 连续自动对焦 crash
缘由:第一次对焦未结束,应用层又发起的第二次对焦,引发对焦失败。
解决方案一:传入 AutoFocusCallback
解决方案二:延时操做
解决方案三:异常捕获
2.2 摄像头个数判断错误
现象:当咱们使用 Camera.getNumberOfCameras()方法检测摄像头数量时返回的结果不许确,若是咱们尝试打开一个不存在的摄像头确定会抛出异常,这也提醒咱们在开启 Camera 摄像头时须要加异常保护。
表明机型:联想 278t 酷派 8022
2.3 闪光灯的判断
咱们经常使用的判断手机是否有闪光灯的方法应该有如下两种:
判断是否支持闪光灯方法一:使用getSupportedFlashModes 方法
判断是否支持闪光灯方法二:经过PackageManager 判断
方法一有 3.7%的机器结果错误,没法准确地判断出手机是否有闪光灯,主要的品牌包含:酷派、天语、联想、三星等。
方法二有 9.7%的机器结果错误,主要品牌包含:VIVO、金立、酷派、天语、朵惟、三星等。咱们建议在判断手机是否有闪光灯的时候将这两种方法联合使用,出现错误的几率将大大下降。
2.4 常亮状态与其余状态间的切换
前提条件是咱们设置闪光灯为常亮(Parameters.FLASH_MODE_TORCH),而且闪光灯成功常亮,此时咱们在设置闪光灯模式为 Parameters.FLASH_MODE_AUTO 后闪光灯依然常亮,这样的机型约占热门机型的12% ,遇到这种状况咱们须要先设置闪光灯模式为Parameters.FLASH_MODE_OFF 关闭闪光灯后再设置其余模式。
2.5 释放 Camera 后闪光灯依旧闪亮
既然开了,咱们就要负责关,说实话,之前这个问题根本不在个人考虑范内,由于咱们在使用 Camera 的时候都会在Activity 被销毁或者暂停时释放 Camera,这个时候不管闪光灯是什么状态,都会随着 Camera 的释放而关闭,直到我碰见了 OPPO R815T,个人世界观发生了变化,这货若是设置了闪光灯常亮,即便释放了 Camera 闪光灯依旧稳稳地亮着,并且因为Camera 被释放掉了,你再也没办法关闭闪光灯了,关闭 App、卸载 App,你仍是扣电池关机吧…..因此,若是你的程序中有设置闪光灯为常亮状态的操做,建议在释放 Camera 前先将闪光灯设置为关闭(Parameters.FLASH_MODE_OFF)状态。
2.6 CameraInfo 的另类状况
官方文档中有关于调整相机预览角度的例子
在这个例子中CameraInfo 很是重要,最终的角度计算就是根据CameraInfo 中orientation 值获得的,因此若是这个值不许确的话那么咱们的角度就有可能出现错误。
VIVO V1 手机第一次咱们获取CameraInfo 的orientation 值是90,而当执行了mCamera =Camera.open();以后再获取CameraInfo 的orientation 值就是0,并且之后获取的都是0 ,除非重启手机。
不管是这款手机上的哪一个应用,只要执行了一次Camera.open()以后,其余全部程序中获取CameraInfo 的orientation 都是是0。
机自带的相机却能很好的使用反编译系统相机后果真发现系统相机并无像官方给出的例子来进行角度的矫正。
解决方案:
双卡的问题解决的基本思路:
1.推断:手机内置的系统APP 均可以正常使用这些功能,所以确定存在厂商自定义API 来实现这些功能;
2.反编译:Framework、系统APP、系统数据库;
3.定位:TelephoneManager 扩展、SMSManager 扩展、电话服务扩展、短信服务扩展、数据
库字段扩展。
说到UI 适配其实非常让人头疼,下面的图片是某个产品为了进行UI 适配所作的工做,能够看出至关繁琐。
除了分辨率的适配,有时候布局文件中的某个标签还会引发一些问题,咱们先看下面一段布局代码:
正确结果:
错误结果:
这就是由于Android3.0 一下版本在FrameLayout 中使用layout_marginTo 标签必需要设置gravity 才能生效。
那么若是解决这个问题呢:
在设置android:layout_marginTop 的组件中再设置一下android:layout_gravity=”top”
1 厂商的抽象方法
若是你须要实现InputConnection 接口,那么你必定要注意下面这个很奇葩的异常:
反编译了下此款手机的framework,发现厂商在InputConnection 接口中增长了一个抽象方法performYLPrivateCommand
2 距离传感器
2.1 不一样手机event.values[0]值简直是变幻无穷
简单说几个有表明性的:
2.2 数值与远近关系不统一
既然咱们是经过数值来判断当前是否出于近耳状态,那么是否是应该这个数值的大小是有说道的,靠近时的数值小一点,远离时的数值大一些,起码我见过的99%的手机是这样子的,可是就有几款神经病手机(100W)恰恰是靠近时的数值比远离时的数值大,这是个坑,开发者要注意~~!!
2.3 getMaximumRange 方法返回值不对
有一句API:
SensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY).getMaximumRange()文档解释这个应该获取的是传感器数值变化的最大范围,好比若是靠近时的值是0,远离时的值是1,那么getMaximumRange()的值应该是1 才不会影响咱们的判断,我这里仅仅是从API 角度和咱们平常的使用习惯来讲的,若是不是这样的规律,就会对咱们的编程形成麻烦。
酷派5890 手机:变化的数值为(3,5),getMaximumRange()的值为10;
华为Y320-T00 手机,变化的数值为(0,10),getMaximumRange()的值为20;
中兴U930HD 手机,变化的数值为(3,100),getMaximumRange()的值为1023;
Bugly是腾讯内部产品质量监控平台的外发版本,其主要功能是App发布之后,对用户侧发生的Crash以及卡顿现象进行监控并上报,让开发同窗能够第一时间了解到App的质量状况,及时机型修改。目前腾讯内部全部的产品,均在使用其进行线上产品的崩溃监控。