Android系统兼容适配踩坑(持续更新)
屏幕亮度范围
在Android应用层,要获取屏幕亮度,一般是通过读取系统Settings表中的配置:
1 | Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS); |
从AOSP源码可以看出,其范围是0到255,如果要修改亮度,也是通过这个key去putInt的:
1 | /** |
原则上无论什么设备,厂商都应该按照这个亮度范围去做类似“归一化”的适配,才能让上层开发者写出可靠的代码。
实际上,这个范围值并不可靠,很多厂商根本没在意这个源码注释中的255上限。这就导致了开发者以为修改成255就是最大亮度,但效果不符合预期。
我们可以通过获取最大亮度的配置值来验证:
1 | int id = getResources().getIdentifier("config_screenBrightnessSettingMaximum", "integer", "android"); |
亲测某Android 11设备获取到的值是2047,而某Android 13设备又是16000多,只有某Android 7设备老老实实返回了255。
解决
说明屏幕厂商和ROM厂商着实坑了一把开发者,源码变得不可信。如果我们要兼容各Android版本,做一个调解屏幕亮度的SeekBar,只能先获取实际的最大亮度,而不是默认它为255。
WiFi芯片支持频率
要判断设备WiFi芯片是否支持5GHz频率,一般是调用WifiManager的is5GHzBandSupported方法,源码如下:
1 | /** |
这是Android SDK的公开接口,从API 21就有了,理论上应该比较靠谱。开发者的预期就是无论何时调用这个方法,返回值都是一样的,因为硬件配置从设备出厂后一般是不会改变的。
实际上,这个方法也不完全可信。经测试,在某Android 7设备上,如果保持WLAN开关开启,可以正常获取到true(支持双频)或false(仅支持2.4GHz),但一旦关闭开关,就只会返回false了,这不符合预期,芯片本身的属性不应该受是否开启影响。
目前暂时没有做大范围测试,不知道是不是只有Android低版本系统有此问题,而在Android 13等较新版本的系统上,不会有这个问题,即便关闭WLAN,也能获取到正确值。
从这个帖子WifiManager.is5GHzBandSupported() lying?也能看出,厂商对这个方法的适配支持的确不靠谱。
解决
如果我们要兼容各Android版本,就只能自行缓存正确值,也就是当返回true时,就记录到本地,以后直接获取缓存值即可;返回false时,就认为值不可靠,不进行缓存。示例如下:
1 | public boolean isWifi5GSupported() { |
这样可以保证应用一旦获取到正确值,后续就可以不再依赖系统接口了。
未完待续
以后有什么坑会继续记录……