4、获取SensorManager:通过getSystemService获取SensorManager实例、检查设备是否支持距离传感器
好,咱们接着往下走。上一节我们把距离传感器的“家底”摸了一遍,知道了它长什么样、能干什么。这一节,咱们要真正动手了——在代码里把它请出来。
说白了,Android系统里所有传感器都归一个管家管,这个管家就叫 SensorManager。你要用距离传感器,第一步就是拿到这个管家的实例。怎么拿?通过 getSystemService()。
4.1 获取SensorManager实例
代码其实就一行,但我建议你把它放在 Activity 或 Fragment 的初始化阶段。我个人习惯在 onCreate() 里做这件事,因为传感器管理器是系统级服务,不会因为配置变化而丢失。
SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
嗯,就这么简单。但这里有个坑——getSystemService() 返回的是 Object,你得强转成 SensorManager。我曾经见过有同事忘了强转,编译直接报错,还跑来问我为什么拿不到传感器……
requireActivity().getSystemService(),别直接用 getActivity(),否则可能空指针。
4.2 检查设备是否支持距离传感器
拿到管家之后,下一步就是问它:嘿,你这儿有没有距离传感器?
为什么要检查?你想想看,不是所有手机都有距离传感器。低端机、平板、甚至某些游戏手机可能就把它砍掉了。如果你不检查就直接注册监听,轻则传感器没反应,重则直接崩溃。
检查方法很简单:
Sensor proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (proximitySensor == null) {
// 设备不支持距离传感器
// 做降级处理或提示用户
} else {
// 设备支持,可以继续使用
}
getDefaultSensor() 会返回系统默认的距离传感器实例。如果返回 null,说明设备不支持。这里要注意,有些设备可能有多个同类型传感器,但 getDefaultSensor() 只返回最常用的那个。我在项目中遇到过一台平板,它有两个距离传感器——一个在正面,一个在背面。但 getDefaultSensor() 只返回了正面的那个。
getDefaultSensor() 返回了非 null 的传感器,但注册监听后死活收不到数据。后来发现是系统定制 ROM 把传感器禁用了。所以,光检查 null 还不够,最好在注册监听后加一个超时判断。
4.3 获取传感器详细信息
如果设备支持,你还可以拿到传感器的更多信息。比如它的名字、厂商、最大测量范围、分辨率等等。这些信息在调试时特别有用。
if (proximitySensor != null) {
String name = proximitySensor.getName();
String vendor = proximitySensor.getVendor();
float maxRange = proximitySensor.getMaximumRange();
float resolution = proximitySensor.getResolution();
float power = proximitySensor.getPower(); // 单位 mA
// 打印出来看看
Log.d("ProximitySensor", "名称: " + name);
Log.d("ProximitySensor", "厂商: " + vendor);
Log.d("ProximitySensor", "最大范围: " + maxRange + " cm");
Log.d("ProximitySensor", "分辨率: " + resolution + " cm");
Log.d("ProximitySensor", "功耗: " + power + " mA");
}
这里有个知识点:距离传感器的 getMaximumRange() 通常返回一个很小的值,比如 5.0 cm 或 8.0 cm。但有些传感器返回的是 1.0,表示它只区分“近”和“远”两种状态。说白了,它就是个二进制开关。
| 属性 | 说明 | 典型值 |
|---|---|---|
| getName() | 传感器名称 | STK3311 Proximity Sensor |
| getVendor() | 传感器厂商 | STMicroelectronics |
| getMaximumRange() | 最大检测距离 | 5.0 cm |
| getResolution() | 分辨率(最小变化量) | 0.01 cm |
| getPower() | 工作功耗 | 0.5 mA |
4.4 完整代码示例
我把上面这些串起来,给你一个可以直接用的模板:
public class MainActivity extends AppCompatActivity {
private SensorManager sensorManager;
private Sensor proximitySensor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 获取 SensorManager
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 2. 检查距离传感器
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (proximitySensor == null) {
// 不支持,做降级处理
Toast.makeText(this, "您的设备不支持距离传感器", Toast.LENGTH_LONG).show();
return;
}
// 3. 打印传感器信息(调试用)
Log.d("Proximity", "传感器名称: " + proximitySensor.getName());
Log.d("Proximity", "最大范围: " + proximitySensor.getMaximumRange() + " cm");
}
}
这段代码你直接复制到项目里就能跑。注意,Toast 只是示例,实际项目中你可能需要隐藏某些 UI 或切换功能逻辑。
4.5 知识体系图
下面这张图把本节的核心逻辑串起来了。你一看就明白:
这张图把整个流程拆成了三步:先拿管家,再问传感器,最后根据结果走不同分支。你写代码的时候脑子里过一遍这个流程,基本不会出错。