屏幕亮度范围

在Android应用层,要获取屏幕亮度,一般是通过读取系统Settings表中的配置:

1
Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS);

从AOSP源码可以看出,其范围是0到255,如果要修改亮度,也是通过这个key去putInt的:

1
2
3
4
/**
* The screen backlight brightness between 0 and 255.
*/
public static final String SCREEN_BRIGHTNESS = "screen_brightness";

原则上无论什么设备,厂商都应该按照这个亮度范围去做类似“归一化”的适配,才能让上层开发者写出可靠的代码。

实际上,这个范围值并不可靠,很多厂商根本没在意这个源码注释中的255上限。这就导致了开发者以为修改成255就是最大亮度,但效果不符合预期。

我们可以通过获取最大亮度的配置值来验证:

1
2
int id = getResources().getIdentifier("config_screenBrightnessSettingMaximum", "integer", "android");
int maxBrightness = getResources().getInteger(id);

亲测某Android 11设备获取到的值是2047,而某Android 13设备又是16000多,只有某Android 7设备老老实实返回了255。

解决

说明屏幕厂商和ROM厂商着实坑了一把开发者,源码变得不可信。如果我们要兼容各Android版本,做一个调解屏幕亮度的SeekBar,只能先获取实际的最大亮度,而不是默认它为255。

WiFi芯片支持频率

要判断设备WiFi芯片是否支持5GHz频率,一般是调用WifiManager的is5GHzBandSupported方法,源码如下:

1
2
3
4
5
6
7
8
9
10
11
/**
* Check if the chipset supports 5GHz band.
* @return {@code true} if supported, {@code false} otherwise.
*/
public boolean is5GHzBandSupported() {
try {
return mService.is5GHzBandSupported();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

这是Android SDK的公开接口,从API 21就有了,理论上应该比较靠谱。开发者的预期就是无论何时调用这个方法,返回值都是一样的,因为硬件配置从设备出厂后一般是不会改变的。

实际上,这个方法也不完全可信。经测试,在某Android 7设备上,如果保持WLAN开关开启,可以正常获取到true(支持双频)或false(仅支持2.4GHz),但一旦关闭开关,就只会返回false了,这不符合预期,芯片本身的属性不应该受是否开启影响。

目前暂时没有做大范围测试,不知道是不是只有Android低版本系统有此问题,而在Android 13等较新版本的系统上,不会有这个问题,即便关闭WLAN,也能获取到正确值。

从这个帖子WifiManager.is5GHzBandSupported() lying?也能看出,厂商对这个方法的适配支持的确不靠谱。

解决

如果我们要兼容各Android版本,就只能自行缓存正确值,也就是当返回true时,就记录到本地,以后直接获取缓存值即可;返回false时,就认为值不可靠,不进行缓存。示例如下:

1
2
3
4
5
6
7
public boolean isWifi5GSupported() {
boolean cache = SPUtil.getBoolean("config_wifi5ghzSupport");
if (cache) return true;
boolean support = mWifiManager != null && mWifiManager.is5GHzBandSupported();
SPUtil.put("config_wifi5ghzSupport", support);
return support;
}

这样可以保证应用一旦获取到正确值,后续就可以不再依赖系统接口了。

未完待续

以后有什么坑会继续记录……