记录拍照时手机的朝向,用指南针可以解决,但有些手机会在仰角超过90度(即仰拍,屏幕朝下时)不能记录正确的方向。
通过用手机的陀螺仪,根据加速度、磁场数据计算手机姿态,通过观察者模式通知状态变化
通过陀螺仪获取://方位角、俯仰角与翻滚角,通过计算获取手机姿态,包括以下:屏幕方向:竖屏、横屏(右上)、横屏(右下),是否仰拍:俯拍、仰拍。
MySensorViewModel用于记录角度,通知观察者
-
- import androidx.lifecycle.MutableLiveData
- import androidx.lifecycle.ViewModel
-
- object MySensorViewModel : ViewModel() {
-
- //竖屏角度
- var currentDegreePortrait = MutableLiveData(0f)
-
- //横屏角度
- var currentDegreeLandscape = MutableLiveData(0f)
-
- }
主要代码,用于监控设备姿态变化,计算后更新ViewModel
-
- import android.content.Context
- import android.hardware.Sensor
- import android.hardware.SensorEvent
- import android.hardware.SensorEventListener
- import android.hardware.SensorManager
-
- /**
- * @ProjectName: mydemo
- * @Package: esa.library.sensor
- * @ClassName: MySensor
- * @Description: java类作用描述
- * @Author: Administrator
- * @CreateDate: 2023/04/06 13:33
- * @UpdateUser: Administrator
- * @UpdateDate: 2023/04/06 13:33
- * @UpdateRemark: 更新说明
- * @Version: 1.0
- */
- class MySensor{
-
- companion object {
- private var instance: MySensor? = null
-
- @Synchronized
- fun getInstance(): MySensor {
- try {
- if (instance == null) {
- instance = MySensor()
- }
- } catch (ex: Exception) {
- instance = MySensor()
- }
- return instance!!
- }
- }
-
- //传感器管理
- private lateinit var sensorManager: SensorManager
-
- //传感器
- private lateinit var sensor: Sensor
-
- /**
- * @param context
- * @return void
- * @description 初始化
- * @author Administrator
- * @time 2023/04/06 13:42
- */
- fun init(context: Context) {
- sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
- val ll = Sensoreventlistener()
- sensorManager.registerListener(ll, null, SensorManager.SENSOR_DELAY_NORMAL)
-
- //注册加速度传感器监听
- val acceleSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
- sensorManager.registerListener(ll, acceleSensor, SensorManager.SENSOR_DELAY_NORMAL)
- //注册磁场传感器监听
- val magSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
- sensorManager.registerListener(ll, magSensor, SensorManager.SENSOR_DELAY_NORMAL)
- }
-
- //加速度参数与磁场参数
- private var gravity: FloatArray? = null
- private var geomagnetic: FloatArray? = null
-
- //上一次刷新时间
- private var lastrefresh = System.currentTimeMillis()
-
- //刷新频率
- private val tik: Long = 500
-
- //方位角、俯仰角与翻滚角
- var values = FloatArray(3)
-
- //传感器监听类
- private inner class Sensoreventlistener : SensorEventListener {
- override fun onSensorChanged(sensorEvent: SensorEvent) {
- if (System.currentTimeMillis() - lastrefresh > tik) {
- lastrefresh = System.currentTimeMillis()
- try {
- when (sensorEvent.sensor.type) {
- Sensor.TYPE_ACCELEROMETER -> gravity = sensorEvent.values.clone()
- Sensor.TYPE_MAGNETIC_FIELD -> geomagnetic = sensorEvent.values.clone()
- }
- //计算-方位角、俯仰角与翻滚角
- if (gravity != null && geomagnetic != null) {
- val R = FloatArray(9)
- if (SensorManager.getRotationMatrix(R, null, gravity, geomagnetic)) {
- SensorManager.getOrientation(R, values)
-
- updateView()
- }
- }
- } catch (ex: Exception) {
- println(ex.toString())
- }
- }
- }
-
- override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
- }
-
- var currentDegreePortrait = 0f
- var currentDegreeLandscape = 0f //横屏角度
-
- /**
- * @param
- * @return void
- * @description 更新数据
- * @author Administrator
- * @time 2023/04/04 16:52
- */
- private fun updateView() {
-
- //横屏
- currentDegreeLandscape = ((360f + values[0] * 180f / Math.PI) % 360).toFloat()
- //右上横屏
- currentDegreeLandscape = (currentDegreeLandscape + 90) % 360
- //右下横屏
- if (values[2] > 0) {
- currentDegreeLandscape = (currentDegreeLandscape + 180) % 360
- }
-
- //竖屏
- currentDegreePortrait = ((360f + values[0] * 180f / Math.PI) % 360).toFloat()
-
- //判断是否有翻转
- //取绝对值
- val v2 = if (values[2] < 0) -values[2] else values[2]
- if (v2 > Math.PI / 2) {
- currentDegreePortrait = (currentDegreePortrait + 180) % 360
- }
-
- // //被观察者的通知更新
- MySensorViewModel.currentDegreePortrait.postValue(currentDegreePortrait)
- MySensorViewModel.currentDegreeLandscape.postValue(currentDegreeLandscape)
- }
- }