【体感手势】口袋模式或者防误触

口袋模式或者防止误触

带有黑屏手势功能的手机,一般都需要进行一个防误触的判断。防止手机放在口袋里或者包包(一些导电介质的东西可能带来辅助效果,比如钥匙)里别误触发点亮屏幕,甚至是打出电话。

原理

接近式传感器的靠近与远离功能。
可以参考我们手机打电话时,耳朵贴近手机的时候,往往屏幕是自动息屏,离开耳朵一小段距离,屏幕又亮起的这个功能。同理和我们放在口袋中一个意思。比较严格的防误触可能会加上Acc重力传感器进行判断

调用方法

原理->基于接近式传感器的远近识别

    private boolean type_proximity = true;
    private ProximitySensorManager mProximitySensorManager;
    
    private void pocketDetector(boolean isEnable){
        if (isEnable && (mProximitySensorManager == null)) {
            mProximitySensorManager = new ProximitySensorManager(mContext, new ProximitySensorManager.Listener() {
                
                @Override
                public void onNear() {
                    // 靠近口袋事件
                    type_proximity = true;
                }
                
                @Override
                public void onFar() {
                    // 远离口袋事件
                    type_proximity = false;
                }
            });
            
            mProximitySensorManager.enable();
        } else if(!isEnable && (mProximitySensorManager != null)){
            mProximitySensorManager.disable(false);
            mProximitySensorManager = null;
        }
        
    }  

其中 ProximitySensorManager.java 是系统自带的源码直接粘贴过来,直接使用即可

系统工具类ProximitySensorManager

package com.android.server.policy;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * Manages the proximity sensor and notifies a listener when enabled.
 */
public class ProximitySensorManager {
    /**
     * Listener of the state of the proximity sensor.
     * <p>
     * This interface abstracts two possible states for the proximity sensor, near and far.
     * <p>
     * The actual meaning of these states depends on the actual sensor.
     */
    public interface Listener {
        /** Called when the proximity sensor transitions from the far to the near state. */
        public void onNear();
        /** Called when the proximity sensor transitions from the near to the far state. */
        public void onFar();
    }

    public static enum State {
        NEAR, FAR
    }

    private final ProximitySensorEventListener mProximitySensorListener;

    /**
     * The current state of the manager, i.e., whether it is currently tracking the state of the
     * sensor.
     */
    private boolean mManagerEnabled;

    /**
     * The listener to the state of the sensor.
     * <p>
     * Contains most of the logic concerning tracking of the sensor.
     * <p>
     * After creating an instance of this object, one should call {@link #register()} and
     * {@link #unregister()} to enable and disable the notifications.
     * <p>
     * Instead of calling unregister, one can call {@link #unregisterWhenFar()} to unregister the
     * listener the next time the sensor reaches the {@link State#FAR} state if currently in the
     * {@link State#NEAR} state.
     */
    private static class ProximitySensorEventListener implements SensorEventListener {
        private static final float FAR_THRESHOLD = 5.0f;

        private final SensorManager mSensorManager;
        private final Sensor mProximitySensor;
        private final float mMaxValue;
        private final Listener mListener;

        /**
         * The last state of the sensor.
         * <p>
         * Before registering and after unregistering we are always in the {@link State#FAR} state.
         */
        private State mLastState;
        /**
         * If this flag is set to true, we are waiting to reach the {@link State#FAR} state and
         * should notify the listener and unregister when that happens.
         */
        private boolean mWaitingForFarState;

        public ProximitySensorEventListener(SensorManager sensorManager, Sensor proximitySensor,Listener listener) {
            mSensorManager = sensorManager;
            mProximitySensor = proximitySensor;
            mMaxValue = proximitySensor.getMaximumRange();
            mListener = listener;
            // Initialize at far state.
            mLastState = State.FAR;
            mWaitingForFarState = false;
        }

        @Override
        public void onSensorChanged(SensorEvent event) {
            // Make sure we have a valid value.
            if (event.values == null) return;
            if (event.values.length == 0) return;
            float value = event.values[0];
            // Convert the sensor into a NEAR/FAR state.
            State state = getStateFromValue(value);
            synchronized (this) {
                // No change in state, do nothing.
                if (state == mLastState) return;
                // Keep track of the current state.
                mLastState = state;
                // If we are waiting to reach the far state and we are now in it, unregister.
                if (mWaitingForFarState && mLastState == State.FAR) {
                    unregisterWithoutNotification();
                }
            }
            // Notify the listener of the state change.
            switch (state) {
                case NEAR:
                    mListener.onNear();
                    break;

                case FAR:
                    mListener.onFar();
                    break;
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // Nothing to do here.
        }

        /** Returns the state of the sensor given its current value. */
        private State getStateFromValue(float value) {
            // Determine if the current value corresponds to the NEAR or FAR state.
            // Take case of the case where the proximity sensor is binary: if the current value is
            // equal to the maximum, we are always in the FAR state.
            return (value > FAR_THRESHOLD || value == mMaxValue) ? State.FAR : State.NEAR;
        }

        /**
         * Unregister the next time the sensor reaches the {@link State#FAR} state.
         */
        public synchronized void unregisterWhenFar() {
            if (mLastState == State.FAR) {
                // We are already in the far state, just unregister now.
                unregisterWithoutNotification();
            } else {
                mWaitingForFarState = true;
            }
        }

        /** Register the listener and call the listener as necessary. */
        public synchronized void register() {
            // It is okay to register multiple times.
            mSensorManager.registerListener(this, mProximitySensor, SensorManager.SENSOR_DELAY_UI);
            // We should no longer be waiting for the far state if we are registering again.
            mWaitingForFarState = false;
        }

        public void unregister() {
            State lastState;
            synchronized (this) {
                unregisterWithoutNotification();
                lastState = mLastState;
                // Always go back to the FAR state. That way, when we register again we will get a
                // transition when the sensor gets into the NEAR state.
                mLastState = State.FAR;
            }
            // Notify the listener if we changed the state to FAR while unregistering.
            if (lastState != State.FAR) {
                mListener.onFar();
            }
        }

        private void unregisterWithoutNotification() {
            mSensorManager.unregisterListener(this);
            mWaitingForFarState = false;
        }
    }

    public ProximitySensorManager(Context context, Listener listener) {
        SensorManager sensorManager =
                (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        Sensor proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        if (proximitySensor == null) {
            // If there is no sensor, we should not do anything.
            mProximitySensorListener = null;
        } else {
            mProximitySensorListener =
                    new ProximitySensorEventListener(sensorManager, proximitySensor, listener);
        }
    }

    /**
     * Enables the proximity manager.
     * <p>
     * The listener will start getting notifications of events.
     * <p>
     * This method is idempotent.
     */
    public void enable() {
        if (mProximitySensorListener != null && !mManagerEnabled) {
            mProximitySensorListener.register();
            mManagerEnabled = true;
        }
    }

    /**
     * Disables the proximity manager.
     * <p>
     * The listener will stop receiving notifications of events, possibly after receiving a last
     * {@link Listener#onFar()} callback.
     * <p>
     * If {@code waitForFarState} is true, if the sensor is not currently in the {@link State#FAR}
     * state, the listener will receive a {@link Listener#onFar()} callback the next time the sensor
     * actually reaches the {@link State#FAR} state.
     * <p>
     * If {@code waitForFarState} is false, the listener will receive a {@link Listener#onFar()}
     * callback immediately if the sensor is currently not in the {@link State#FAR} state.
     * <p>
     * This method is idempotent.
     */
    public void disable(boolean waitForFarState) {
        if (mProximitySensorListener != null && mManagerEnabled) {
            if (waitForFarState) {
                mProximitySensorListener.unregisterWhenFar();
            } else {
                mProximitySensorListener.unregister();
            }
            mManagerEnabled = false;
        }
    }
}

结论

实践证明系统的提供的判断误触的工具栏非常好用,简单粗暴又省电,还有稳定得没亲妈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值