欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

手机传感器辅助类

程序员文章站 2022-04-19 10:22:04
...

SensorUtil.java

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Message;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

import java.util.ArrayList;
import java.util.List;

/**
 * 传感器管理
 */
public class SensorUtil {

    private static SensorUtil instance = null;

    public static SensorUtil getInstance() {
        if (instance == null) {
            synchronized (SensorUtil.class) {
                if (instance == null) {
                    instance = new SensorUtil();
                }
            }
        }
        return instance;
    }

    public static SensorUtil newInstance(Context activityContext) {
        SensorUtil sensorUtil = new SensorUtil();
        sensorUtil.init(activityContext);
        return sensorUtil;
    }

    private SensorUtil() {

    }

    /**
     * 窗体的context
     */
    private Context context = null;

    /**
     * 传感器服务
     */
    private SensorManager sensorManager = null;

    /**
     * 传感器:加速度
     */
    private float[] gravity = null;

    /**
     * 传感器:环境磁场
     */
    private float[] geomagnetic = null;

    /**
     * 屏幕方向
     */
    private int surfaceRotation = Surface.ROTATION_0;

    /**
     * 手机屏幕方向
     */
    private int axisX = SensorManager.AXIS_Y;

    /**
     * 手机屏幕方向
     */
    private int axisY = SensorManager.AXIS_X;

    /**
     * 方位角(0~360)
     * 手机围绕Z轴旋转,正北方向为0度,顺时针旋转,方位角从0到360度变化,正北0度、正东90度,正南180度,正西270度。
     */
    private float orientation = -1;

    /**
     * 横滚角(-90~90)
     * 当手机zy轴所在的平面与地面垂直时,此时横滚角是0度,手机围绕y轴旋转,若顺时针旋转,横滚角从0到90度变化。如果逆时针旋转,横滚角从0到-90度变化。
     */
    private float roll = -1;

    /**
     * 俯仰角(-90~90)
     * 当手机xy轴所在的平面与地面平行时,此时俯仰角是0度,当手机围绕x轴旋转,且顶部离你越来越远,底部离你越来越近时(此时可以理解成,手机逐渐朝着地面拍摄),俯仰角从0到-90度变化;如果顶部离你越来越近,底部离你越来越远时(此时可以理解成,手机逐渐朝着天空拍摄),俯仰角从0到90度变化
     */
    private float tilt = -1;

    private List<SensorListener> sensorListeners = new ArrayList<>();

    /**
     * 初始化
     * @param activityContext Activity上下文
     */
    public void init(Context activityContext) {
        if (activityContext == null) {
            return;
        }

        this.context = activityContext;

        sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
    }

    /**
     * 资源释放
     */
    public void release() {
        if (sensorManager != null) {
            sensorManager.unregisterListener(sensorEventListener);
            sensorManager = null;
            gravity = null;
            geomagnetic = null;
        }
    }

    /**
     * 添加传感器监听
     * @param listener 监听事件
     */
    public void addSensorListener(SensorListener listener) {
        if (listener == null) {
            return;
        }

        if (sensorListeners != null && sensorListeners.contains(listener) == false) {
            sensorListeners.add(listener);
        }

        if (orientation >= 0) {
            listener.updateOrientation(surfaceRotation, orientation, roll, tilt);
        }

        if (gravity != null) {
            listener.updateGravity(gravity);
        }

        if (geomagnetic != null) {
            listener.updateGeomagnetic(geomagnetic);
        }
    }

    /**
     * 移除监听事件
     */
    public void removeSensorListener(SensorListener listener) {
        if (listener == null) {
            return;
        }

        if (sensorListeners != null && sensorListeners.contains(listener)) {
            sensorListeners.remove(listener);
        }
    }

    /**
     * 清空监听事件
     */
    public void clearSensorListener() {
        sensorListeners.clear();
    }

    /**
     * 兼容横竖屏
     */
    private void updateCoordinate() {
        WindowManager windowManager = ((Activity)context).getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        surfaceRotation = display.getRotation();
        switch (surfaceRotation) {
            // 正向竖屏
            case Surface.ROTATION_0:
                axisX = SensorManager.AXIS_Y;
                axisY = SensorManager.AXIS_X;
                break;
            // 正向横屏
            case Surface.ROTATION_90:
                axisX = SensorManager.AXIS_X;
                axisY = SensorManager.AXIS_Y;
                break;
            case Surface.ROTATION_180:
                break;
            case Surface.ROTATION_270:
                break;
            default:
                break;
        }
    }

    /**
     * 传感器监听
     */
    private SensorEventListener sensorEventListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {
            switch (event.sensor.getType()) {
                // 加速度传感器
                case Sensor.TYPE_ACCELEROMETER:
                    gravity = event.values;
                    handler.sendEmptyMessage(0);

                    sensorListeners.forEach(listener -> listener.updateGravity(gravity));
                    break;
                // 磁场传感器
                case Sensor.TYPE_MAGNETIC_FIELD:
                    geomagnetic = event.values;
                    handler.sendEmptyMessage(0);

                    sensorListeners.forEach(listener -> listener.updateGeomagnetic(geomagnetic));
                    break;
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    };

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if(gravity != null && geomagnetic != null) {
                float[] inR = new float[9];
                if(SensorManager.getRotationMatrix(inR, null, gravity, geomagnetic)) {
                    updateCoordinate();
                    float[] outR = new float[9];
                    SensorManager.remapCoordinateSystem(inR, axisX, axisY, outR);
                    float[] values = new float[3];
                    SensorManager.getOrientation(outR, values);
                    orientation = (float) ((360f + Math.toDegrees(values[0])) % 360);
                    tilt = (float) Math.toDegrees(values[1]);
                    roll = (float) Math.toDegrees(values[2]);

                    float tempTilt = 0;
                    if (axisX == SensorManager.AXIS_X) {
                        // 横屏
                        if (orientation < 270 && orientation >=0) {
                            orientation += 90;
                        } else {
                            orientation -= 270;
                        }
                        tempTilt = tilt;
                        tilt = Math.abs(roll) - 90;
                        roll = -tempTilt;
                    } else {
                        // 竖屏
                        if (orientation < 90 && orientation >= 0) {
                            orientation += 270;
                        } else {
                            orientation -= 90;
                        }
                        tempTilt = tilt;
                        tilt = Math.abs(roll) - 90;
                        roll = tempTilt;
                    }

                    sensorListeners.forEach(listener -> listener.updateOrientation(surfaceRotation, orientation, roll, tilt));
                }
            }
        }
    };

    /**
     * 传感器监听事件
     */
    public interface SensorListener {

        void updateOrientation(int surfaceRotation, float orientation, float roll, float tilt);

        void updateGravity(float[] gravity);

        void updateGeomagnetic(float[] geomagnetic);
    }

    /**
     * 传感器监听事件的抽象类
     */
    public abstract static class AbstractSensorValue implements SensorListener{

        @Override
        public void updateOrientation(int surfaceRotation, float orientation, float roll, float tilt) {

        }

        @Override
        public void updateGravity(float[] gravity) {

        }

        @Override
        public void updateGeomagnetic(float[] geomagnetic) {

        }
    }
}

调用方法

private SensorUtil sensorUtil;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    sensorUtil = SensorUtil.newInstance(this);

    sensorUtil.addSensorListener(new SensorUtil.AbstractSensorValue() {
        @Override
        public void updateOrientation(int surfaceRotation, float orientation, float roll, float tilt) {
            switch (surfaceRotation) {
                case Surface.ROTATION_0:
                    dataBinding.tvScreenOrientation.setText("正向竖屏");
                    break;
                case Surface.ROTATION_90:
                    dataBinding.tvScreenOrientation.setText("正向横屏");
                    break;
                case Surface.ROTATION_180:
                    dataBinding.tvScreenOrientation.setText("反向竖屏");
                    break;
                case Surface.ROTATION_270:
                    dataBinding.tvScreenOrientation.setText("反向横屏");
                    break;
            }
            dataBinding.tvOrientation.setText(String.valueOf(orientation));
            dataBinding.tvRoll.setText(String.valueOf(roll));
            dataBinding.tvTilt.setText(String.valueOf(tilt));
        }

        @Override
        public void updateGravity(float[] gravity) {
            String result = "[";
            if (gravity != null && gravity.length > 0) {
                for (int i = 0; i < gravity.length; i++) {
                    if (i < gravity.length - 1) {
                        result += gravity[i] + ", ";
                    } else {
                        result += String.valueOf(gravity[i]);
                    }
                }
            }
            result += "]";
            dataBinding.tvGravity.setText(result);
        }

        @Override
        public void updateGeomagnetic(float[] geomagnetic) {
            String result = "[";
            if (geomagnetic != null && geomagnetic.length > 0) {
                for (int i = 0; i < geomagnetic.length; i++) {
                    if (i < geomagnetic.length - 1) {
                        result += geomagnetic[i] + ", ";
                    } else {
                        result += String.valueOf(geomagnetic[i]);
                    }
                }
            }
            result += "]";
            dataBinding.tvGeomagnetic.setText(result);
        }
    });
}

@Override
protected void onDestroy() {
    sensorUtil.clearSensorListener();
    sensorUtil.release();
    sensorUtil = null;
    super.onDestroy();
}

测试效果

手机传感器辅助类
手机传感器辅助类
手机传感器辅助类