4、获取SensorManager:通过getSystemService获取SensorManager实例、检查设备是否支持距离传感器

好,咱们接着往下走。上一节我们把距离传感器的“家底”摸了一遍,知道了它长什么样、能干什么。这一节,咱们要真正动手了——在代码里把它请出来。

说白了,Android系统里所有传感器都归一个管家管,这个管家就叫 SensorManager。你要用距离传感器,第一步就是拿到这个管家的实例。怎么拿?通过 getSystemService()

4.1 获取SensorManager实例

代码其实就一行,但我建议你把它放在 ActivityFragment 的初始化阶段。我个人习惯在 onCreate() 里做这件事,因为传感器管理器是系统级服务,不会因为配置变化而丢失。

SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

嗯,就这么简单。但这里有个坑——getSystemService() 返回的是 Object,你得强转成 SensorManager。我曾经见过有同事忘了强转,编译直接报错,还跑来问我为什么拿不到传感器……

小提示:如果你在 Fragment 里写,记得用 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
核心要点:获取 SensorManager 和检查传感器支持,是使用距离传感器的“入场券”。这两步做扎实了,后面的注册监听、数据处理才能跑得稳。千万别跳过检查直接干活,否则线上 crash 会让你哭的。

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 知识体系图

下面这张图把本节的核心逻辑串起来了。你一看就明白:

获取SensorManager与检查传感器支持 getSystemService() 获取SensorManager实例 getDefaultSensor() 检查TYPE_PROXIMITY 判断 null ? ✅ 支持 获取详细信息,注册监听 ❌ 不支持 降级处理,提示用户 核心流程:获取管家 → 询问传感器 → 根据结果走不同分支

这张图把整个流程拆成了三步:先拿管家,再问传感器,最后根据结果走不同分支。你写代码的时候脑子里过一遍这个流程,基本不会出错。


公众号:蓝海资料掘金营,微信deep3321