package com.google.android.stardroid.util;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import com.google.android.stardroid.activities.CompassCalibrationActivity;
import com.google.android.stardroid.base.TimeConstants;
import javax.inject.Inject;
/**
* Monitors the compass accuracy and if it is not medium or high warns the user.
* Created by johntaylor on 4/24/16.
*/
public class SensorAccuracyMonitor implements SensorEventListener {
private static final String TAG = MiscUtil.getTag(SensorAccuracyMonitor.class);
private static final String LAST_CALIBRATION_WARNING_PREF_KEY = "Last calibration warning time";
private SensorManager sensorManager;
private Sensor compassSensor;
private Context context;
private SharedPreferences sharedPreferences;
private Toaster toaster;
@Inject
SensorAccuracyMonitor(
SensorManager sensorManager, Context context, SharedPreferences sharedPreferences,
Toaster toaster) {
Log.d(TAG, "Creating new accuracy monitor");
this.sensorManager = sensorManager;
this.context = context;
this.sharedPreferences = sharedPreferences;
this.toaster = toaster;
compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
private boolean started = false;
private boolean hasReading = false;
/**
* Starts monitoring.
*/
public void start() {
if (started) {
return;
}
Log.d(TAG, "Starting monitoring compass accuracy");
if (compassSensor != null) {
sensorManager.registerListener(this, compassSensor, SensorManager.SENSOR_DELAY_UI);
}
started = true;
}
/**
* Stops monitoring. It's important this is called to disconnect from the sensors and
* ensure the app does not needlessly consume power when in the background.
*/
public void stop() {
Log.d(TAG, "Stopping monitoring compass accuracy");
started = false;
hasReading = false;
sensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (!hasReading) {
onAccuracyChanged(event.sensor, event.accuracy);
}
}
private static final long MIN_INTERVAL_BETWEEN_WARNINGS =
60 * TimeConstants.MILLISECONDS_PER_SECOND;
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
hasReading = true;
if (accuracy == SensorManager.SENSOR_STATUS_ACCURACY_HIGH
|| accuracy == SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
return; // OK
}
Log.d(TAG, "Compass accuracy insufficient");
long nowMillis = System.currentTimeMillis();
long lastWarnedMillis = sharedPreferences.getLong(LAST_CALIBRATION_WARNING_PREF_KEY, 0);
if (nowMillis - lastWarnedMillis < MIN_INTERVAL_BETWEEN_WARNINGS) {
Log.d(TAG, "...but too soon to warn again");
return;
}
sharedPreferences.edit().putLong(LAST_CALIBRATION_WARNING_PREF_KEY, nowMillis).apply();
boolean dontShowDialog = sharedPreferences.getBoolean(
CompassCalibrationActivity.DONT_SHOW_CALIBRATION_DIALOG, false);
if (dontShowDialog) {
toaster.toastLong("Inaccurate compass - please calibrate");
} else {
Intent intent = new Intent(context, CompassCalibrationActivity.class);
intent.putExtra(CompassCalibrationActivity.HIDE_CHECKBOX, false);
context.startActivity(intent);
}
}
}