/*
* This source is part of the
* _____ ___ ____
* __ / / _ \/ _ | / __/___ _______ _
* / // / , _/ __ |/ _/_/ _ \/ __/ _ `/
* \___/_/|_/_/ |_/_/ (_)___/_/ \_, /
* /___/
* repository.
*
* Copyright (C) 2013 Benoit 'BoD' Lubek (BoD@JRAF.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jraf.android.bikey.backend.compass;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import org.jraf.android.bikey.app.Application;
import org.jraf.android.util.listeners.Listeners;
import org.jraf.android.util.log.Log;
public class CompassManager {
private static final CompassManager INSTANCE = new CompassManager();
public static final int RATE = 400;
public static CompassManager get() {
return INSTANCE;
}
private Context mContext;
private Listeners<CompassListener> mListeners = new Listeners<CompassListener>() {
@Override
protected void onFirstListener() {
startListening();
}
@Override
protected void onNoMoreListeners() {
stopListening();
}
};
protected float[] mLastAccelerometerValues;
private CompassManager() {
mContext = Application.getApplication();
}
public void addListener(CompassListener listener) {
mListeners.add(listener);
}
public void removeListener(CompassListener listener) {
mListeners.remove(listener);
}
protected void startListening() {
Log.d();
SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
sensorManager.registerListener(mAccelerometerSensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
sensorManager.registerListener(mMagneticFieldSensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_UI);
}
protected void stopListening() {
Log.d();
SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
sensorManager.unregisterListener(mAccelerometerSensorEventListener);
sensorManager.unregisterListener(mMagneticFieldSensorEventListener);
}
private SensorEventListener mAccelerometerSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
mLastAccelerometerValues = event.values.clone();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
};
private SensorEventListener mMagneticFieldSensorEventListener = new SensorEventListener() {
private float[] mInR = new float[16];
private float[] mOutR = new float[16];
private long mLastDate;
@Override
public void onSensorChanged(SensorEvent event) {
// Log.d();
// if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) return;
if (System.currentTimeMillis() - mLastDate < RATE) return;
float[] values = event.values.clone();
mLastDate = System.currentTimeMillis();
if (mLastAccelerometerValues == null) return;
boolean ok = SensorManager.getRotationMatrix(mInR, null, mLastAccelerometerValues, values);
if (ok) {
SensorManager.remapCoordinateSystem(mInR, SensorManager.AXIS_X, SensorManager.AXIS_Z, mOutR);
float[] deviceOrientation = new float[3];
SensorManager.getOrientation(mOutR, deviceOrientation);
float azimuth = deviceOrientation[0];
float value = 1f - (float) (azimuth / (2 * Math.PI));
mListeners.dispatch(listener -> listener.onCompassChange(value));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
};
}