You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android编程:如何根据距离传感器数值控制屏幕开关?

嘿,这个需求挺实用的,我之前做过类似功能,给你整理了一套完整的实现方案,一步步来:

1. 声明必要权限

首先在AndroidManifest.xml中添加控制屏幕所需的权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />

注:距离传感器属于普通硬件传感器,不需要额外申请权限。

2. 初始化传感器与屏幕控制组件

先获取传感器管理器实例,再找到距离传感器;同时初始化PowerManager和WakeLock,用于控制屏幕亮灭:

Kotlin 示例代码

private lateinit var sensorManager: SensorManager
private var proximitySensor: Sensor? = null
private var wakeLock: PowerManager.WakeLock? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 初始化传感器管理器
    sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
    // 获取距离传感器(TYPE_PROXIMITY)
    proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

    // 初始化PowerManager和WakeLock
    val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
    wakeLock = powerManager.newWakeLock(
        PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
        "MyApp:ProximityWakeLock" // 自定义标签,用于调试
    )

    // 检查设备是否支持距离传感器
    if (proximitySensor == null) {
        Toast.makeText(this, "当前设备不支持距离传感器", Toast.LENGTH_SHORT).show()
        finish()
    }
}

Java 示例代码

private SensorManager sensorManager;
private Sensor proximitySensor;
private PowerManager.WakeLock wakeLock;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(
            PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
            "MyApp:ProximityWakeLock"
    );

    if (proximitySensor == null) {
        Toast.makeText(this, "当前设备不支持距离传感器", Toast.LENGTH_SHORT).show();
        finish();
    }
}
3. 实现传感器事件监听

创建SensorEventListener,在onSensorChanged方法中根据距离值控制屏幕:

Kotlin 示例代码

private val proximityListener = object : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent?) {
        event ?: return
        // 距离传感器返回的数值,单位通常为厘米
        val distance = event.values[0]
        
        // 大多数设备中,0.0代表物体贴近传感器
        if (distance == 0.0f) {
            // 贴近时关闭屏幕:释放WakeLock并清除屏幕常亮标志
            if (wakeLock?.isHeld == true) {
                wakeLock?.release()
            }
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        } else {
            // 远离时唤醒屏幕:获取WakeLock并添加屏幕常亮标志
            if (!wakeLock?.isHeld!!) {
                wakeLock?.acquire(1000) // 持有1秒足够唤醒屏幕,可按需调整时长
            }
            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        // 传感器精度变化时的处理,一般无需额外操作
    }
}

Java 示例代码

private SensorEventListener proximityListener = new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        float distance = event.values[0];
        
        if (distance == 0.0f) {
            // 贴近时关闭屏幕
            if (wakeLock.isHeld()) {
                wakeLock.release();
            }
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        } else {
            // 远离时唤醒屏幕
            if (!wakeLock.isHeld()) {
                wakeLock.acquire(1000);
            }
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // 精度变化处理
    }
};
4. 注册与注销传感器监听

在Activity生命周期中注册和注销监听,避免资源泄漏:

Kotlin 示例代码

override fun onResume() {
    super.onResume()
    // 注册传感器监听,SENSOR_DELAY_NORMAL代表正常采样频率
    proximitySensor?.let {
        sensorManager.registerListener(proximityListener, it, SensorManager.SENSOR_DELAY_NORMAL)
    }
}

override fun onPause() {
    super.onPause()
    // 注销监听,释放WakeLock
    sensorManager.unregisterListener(proximityListener)
    if (wakeLock?.isHeld == true) {
        wakeLock?.release()
    }
}

override fun onDestroy() {
    super.onDestroy()
    // 最终销毁时确保释放WakeLock
    wakeLock?.release()
}

Java 示例代码

@Override
protected void onResume() {
    super.onResume();
    if (proximitySensor != null) {
        sensorManager.registerListener(proximityListener, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
    }
}

@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(proximityListener);
    if (wakeLock.isHeld()) {
        wakeLock.release();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (wakeLock.isHeld()) {
        wakeLock.release();
    }
}
5. 关键注意事项
  • 设备兼容性:不同厂商的距离传感器返回值范围可能不同,部分设备贴近时返回的是接近0的小数而非严格0.0,建议测试时打印distance值做适配。
  • 电量优化:不要长时间持有WakeLock,按需获取和释放,避免不必要的电量消耗。
  • 后台运行:如果需要在后台持续监听传感器,必须使用前台服务,否则系统会限制后台APP的传感器使用权限。
  • 权限适配:Android 12及以上版本,WAKE_LOCK权限无需动态申请,但后台唤醒可能需要额外的权限配置。

内容的提问来源于stack exchange,提问作者Saleh Masoudi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:31:54