/* * Copyright 2012 Greg Milette and Adam Stroud * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package root.gast.playground.sensor.movement; import java.io.File; import java.util.HashMap; import java.util.List; import root.gast.playground.R; import root.gast.speech.SpeechRecognizingAndSpeakingActivity; import android.content.SharedPreferences; import android.hardware.Sensor; import android.hardware.SensorManager; import android.media.AudioManager; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.Engine; import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.CheckBox; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.ToggleButton; import com.androidplot.xy.BoundaryMode; import com.androidplot.xy.XYPlot; /** * Determines when the device has been moved and notifies the user. * * @author Adam Stroud <<a href="mailto:adam.stroud@gmail.com">adam.stroud@gmail.com</a>> */ public class DetermineMovementActivity extends SpeechRecognizingAndSpeakingActivity { private static final String TAG = "DetermineMovementActivity"; private static final int RATE = SensorManager.SENSOR_DELAY_NORMAL; private static final String USE_HIGH_PASS_FILTER_PREFERENCE_KEY = "USE_HIGH_PASS_FILTER_PREFERENCE_KEY"; private static final String USE_TTS_NOTIFICATION_PREFERENCE_KEY = "USE_TTS_NOTIFICATION_PREFERENCE_KEY"; private static final String SELECTED_SENSOR_TYPE_PREFERENCE_KEY = "SELECTED_SENSOR_TYPE_PREFERENCE_KEY"; private static final int TTS_STREAM = AudioManager.STREAM_NOTIFICATION; private SensorManager sensorManager; private TextToSpeech tts; private RadioGroup sensorSelector; private int selectedSensorType; private boolean readingAccelerationData; private SharedPreferences preferences; private AccelerationEventListener accelerometerListener; private AccelerationEventListener linearAccelerationListener; private boolean useTtsNotification; private boolean useHighPassFilter; private XYPlot xyPlot; private CheckBox ttsNotificationsCheckBox; private CheckBox highPassFilterCheckBox; private HashMap<String, String> ttsParams; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.determine_movement); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); ttsParams = new HashMap<String, String>(); ttsParams.put(Engine.KEY_PARAM_STREAM, String.valueOf(TTS_STREAM)); this.setVolumeControlStream(TTS_STREAM); sensorSelector = (RadioGroup)findViewById(R.id.sensorSelector); ttsNotificationsCheckBox = (CheckBox)findViewById(R.id.ttsNotificationsCheckBox); highPassFilterCheckBox = (CheckBox)findViewById(R.id.highPassFilterCheckBox); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); readingAccelerationData = false; preferences = getPreferences(MODE_PRIVATE); useHighPassFilter = getResources().getBoolean(R.bool.useHighPassFilterDefaultValue); useHighPassFilter = preferences.getBoolean(USE_HIGH_PASS_FILTER_PREFERENCE_KEY, useHighPassFilter); ((CheckBox)findViewById(R.id.highPassFilterCheckBox)).setChecked(useHighPassFilter); useTtsNotification = getResources().getBoolean(R.bool.useTtsDefaultValue); useTtsNotification = preferences.getBoolean(USE_TTS_NOTIFICATION_PREFERENCE_KEY, useTtsNotification); ((CheckBox)findViewById(R.id.ttsNotificationsCheckBox)).setChecked(useTtsNotification); selectedSensorType = preferences.getInt(SELECTED_SENSOR_TYPE_PREFERENCE_KEY, Sensor.TYPE_ACCELEROMETER); if (selectedSensorType == Sensor.TYPE_ACCELEROMETER) { ((RadioButton)findViewById(R.id.accelerometer)).setChecked(true); } else { ((RadioButton)findViewById(R.id.linearAcceleration)).setChecked(true); } xyPlot = (XYPlot)findViewById(R.id.XYPlot); xyPlot.setDomainLabel("Elapsed Time (ms)"); xyPlot.setRangeLabel("Acceleration (m/sec^2)"); xyPlot.setBorderPaint(null); xyPlot.disableAllMarkup(); xyPlot.setRangeBoundaries(-10, 10, BoundaryMode.FIXED); } @Override protected void onPause() { super.onPause(); stopReadingAccelerationData(); if (tts != null) { tts.shutdown(); } } @Override public void onSuccessfulInit(TextToSpeech tts) { super.onSuccessfulInit(tts); this.tts = tts; } public void onSensorSelectorClick(View view) { int selectedSensorId = sensorSelector.getCheckedRadioButtonId(); if (selectedSensorId == R.id.accelerometer) { selectedSensorType = Sensor.TYPE_ACCELEROMETER; } else if (selectedSensorId == R.id.linearAcceleration) { selectedSensorType = Sensor.TYPE_LINEAR_ACCELERATION; } preferences .edit() .putInt(SELECTED_SENSOR_TYPE_PREFERENCE_KEY, selectedSensorType) .commit(); } public void onReadAccelerationDataToggleButtonClicked(View view) { ToggleButton toggleButton = (ToggleButton)view; if (toggleButton.isChecked()) { startReadingAccelerationData(); } else { stopReadingAccelerationData(); } } private void startReadingAccelerationData() { if (!readingAccelerationData) { // Clear any plot that may already exist on the chart xyPlot.clear(); xyPlot.redraw(); // Disable UI components so they cannot be changed while plotting // sensor data for (int i = 0; i < sensorSelector.getChildCount(); i++) { sensorSelector.getChildAt(i).setEnabled(false); } ttsNotificationsCheckBox.setEnabled(false); highPassFilterCheckBox.setEnabled(false); // Data files are stored on the external cache directory so they can // be pulled off of the device by the user File accelerometerDataFile = new File(getExternalCacheDir(), "accelerometer.csv"); File linearAcceclerationDataFile = new File(getExternalCacheDir(), "linearAcceleration.csv"); if (selectedSensorType == Sensor.TYPE_ACCELEROMETER) { xyPlot.setTitle("Sensor.TYPE_ACCELEROMETER"); accelerometerListener = new AccelerationEventListener(xyPlot, useHighPassFilter, accelerometerDataFile, (useTtsNotification ? tts : null), ttsParams, getString(R.string.movementDetectedText)); linearAccelerationListener = new AccelerationEventListener(null, useHighPassFilter, linearAcceclerationDataFile, (useTtsNotification ? tts : null), ttsParams, getString(R.string.movementDetectedText)); } else { xyPlot.setTitle("Sensor.TYPE_LINEAR_ACCELERATION"); accelerometerListener = new AccelerationEventListener(null, useHighPassFilter, accelerometerDataFile, (useTtsNotification ? tts : null), ttsParams, getString(R.string.movementDetectedText)); linearAccelerationListener = new AccelerationEventListener(xyPlot, useHighPassFilter, linearAcceclerationDataFile, (useTtsNotification ? tts : null), ttsParams, getString(R.string.movementDetectedText)); } sensorManager.registerListener(accelerometerListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), RATE); sensorManager.registerListener(linearAccelerationListener, sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), RATE); readingAccelerationData = true; Log.d(TAG, "Started reading acceleration data"); } } private void stopReadingAccelerationData() { if (readingAccelerationData) { // Re-enable sensor and options UI views for (int i = 0; i < sensorSelector.getChildCount(); i++) { sensorSelector.getChildAt(i).setEnabled(true); } ttsNotificationsCheckBox.setEnabled(true); highPassFilterCheckBox.setEnabled(true); sensorManager.unregisterListener(accelerometerListener); sensorManager.unregisterListener(linearAccelerationListener); // Tell listeners to clean up after themselves accelerometerListener.stop(); linearAccelerationListener.stop(); readingAccelerationData = false; Log.d(TAG, "Stopped reading acceleration data"); } } public void onTtsNotificationsCheckBoxClicked(View view) { useTtsNotification = ((CheckBox)view).isChecked(); preferences .edit() .putBoolean(USE_TTS_NOTIFICATION_PREFERENCE_KEY, useTtsNotification) .commit(); } public void onHighPassFilterCheckBoxClicked(View view) { useHighPassFilter = ((CheckBox)view).isChecked(); preferences .edit() .putBoolean(USE_HIGH_PASS_FILTER_PREFERENCE_KEY, useHighPassFilter) .commit(); } @Override protected void receiveWhatWasHeard(List<String> heard, float[] confidenceScores) { // no-op } }