This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
public class AccelerometerData { | |
public double value; | |
public float x; | |
public float y; | |
public float z; | |
public long time; | |
public boolean isRealPeak = true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.widget.TextView; | |
import androidx.appcompat.app.AppCompatActivity; | |
import java.util.Calendar; | |
public class CustomAlgoResultsActivity extends AppCompatActivity { | |
private TextView mTotalStepsTextView; | |
private TextView mTotalDistanceTextView; | |
private TextView mTotalDurationTextView; | |
private TextView mAverageSpeedTextView; | |
private TextView mAveragFrequencyTextView; | |
private TextView mTotalCalorieBurnedTextView; | |
private TextView mPhysicalActivityTypeTextView; | |
StepsTrackerDBHelper mStepsTrackerDBHelper; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.capability_layout); | |
mStepsTrackerDBHelper = new StepsTrackerDBHelper(this); | |
mTotalStepsTextView = (TextView) findViewById(R.id.total_steps); | |
mTotalDistanceTextView = (TextView) findViewById(R.id.total_distance); | |
mTotalDurationTextView = (TextView) findViewById(R.id.total_duration); | |
mAverageSpeedTextView = (TextView) findViewById(R.id.average_speed); | |
mAveragFrequencyTextView = (TextView) findViewById(R.id.average_frequency); | |
mTotalCalorieBurnedTextView = (TextView) findViewById(R.id.calories_burned); | |
mPhysicalActivityTypeTextView = (TextView) findViewById(R.id.physical_activitytype); | |
Intent stepsAnalysisIntent = new Intent(getApplicationContext(), StepsTrackerService.class); | |
startService(stepsAnalysisIntent); | |
calculateDataMatrix(); | |
} | |
public void calculateDataMatrix() { | |
Calendar calendar = Calendar.getInstance(); | |
String todayDate = String.valueOf(calendar.get(Calendar.MONTH)+1)+"/" + String.valueOf(calendar.get(Calendar.DAY_OF_MONTH))+"/"+String.valueOf(calendar.get(Calendar.YEAR)); | |
int stepType[] = mStepsTrackerDBHelper.getStepsByDate(todayDate); | |
int walkingSteps = stepType[0]; | |
int joggingSteps = stepType[1]; | |
int runningSteps = stepType[2]; | |
//Calculating total steps | |
int totalStepTaken = walkingSteps + joggingSteps + runningSteps; | |
mTotalStepsTextView.setText(String.valueOf(totalStepTaken)+ " Steps"); | |
//Calculating total distance traveled | |
float totalDistance = walkingSteps*0.5f + joggingSteps * 1.0f + runningSteps * 1.5f; | |
mTotalDistanceTextView.setText(String.valueOf(totalDistance)+" meters"); | |
//Calculating total duration | |
float totalDuration = walkingSteps*1.0f + joggingSteps * 0.7f + runningSteps * 0.4f; | |
float hours = totalDuration / 3600; | |
float minutes = (totalDuration % 3600) / 60; | |
float seconds = totalDuration % 60; | |
mTotalDurationTextView.setText(String.format("%.0f",hours) + " hrs " + String.format("%.0f",minutes) + " mins " + String.format("%.0f",seconds)+ " secs"); | |
//Calculating average speed | |
if(totalDistance>0) { | |
mAverageSpeedTextView.setText(String.format("%.2f", totalDistance / totalDuration) + " meter per seconds"); | |
} else { | |
mAverageSpeedTextView.setText("0 meter per seconds"); | |
} | |
//Calculating average step frequency | |
if(totalStepTaken>0) { | |
mAveragFrequencyTextView.setText(String.format("%.0f", totalStepTaken / minutes) + " steps per minute"); | |
} else { | |
mAveragFrequencyTextView.setText("0 steps per minute"); | |
} | |
//Calculating total calories burned | |
float totalCaloriesBurned = walkingSteps * 0.05f + joggingSteps * 0.1f + runningSteps * 0.2f; | |
mTotalCalorieBurnedTextView.setText(String.format("%.0f",totalCaloriesBurned)+" Calories"); | |
//Calculating type of physical activity | |
mPhysicalActivityTypeTextView.setText(String.valueOf(walkingSteps) + " Walking Steps " + "\n"+String.valueOf(joggingSteps) + " Jogging Steps " + | |
"\n"+String.valueOf(runningSteps)+ " Running Steps"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
public class DateStepsModel { | |
public String mDate; | |
public int mStepCount; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.content.Context; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.BaseAdapter; | |
import android.widget.TextView; | |
import java.util.ArrayList; | |
public class ListAdapter extends BaseAdapter { | |
TextView mDateStepCountText; | |
ArrayList<DateStepsModel> mStepCountList; | |
Context mContext; | |
LayoutInflater mLayoutInflater; | |
public ListAdapter(ArrayList<DateStepsModel> mStepCountList, Context mContext) { | |
this.mStepCountList = mStepCountList; | |
this.mContext = mContext; | |
this.mLayoutInflater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); | |
} | |
@Override | |
public int getCount() { | |
return mStepCountList.size(); | |
} | |
@Override | |
public Object getItem(int position) { | |
return mStepCountList.get(position); | |
} | |
@Override | |
public long getItemId(int position) { | |
return position; | |
} | |
@Override | |
public View getView(int position, View convertView, ViewGroup parent) { | |
if (convertView == null) { | |
convertView = mLayoutInflater.inflate(R.layout.list_rows, parent, false); | |
} | |
mDateStepCountText = (TextView) convertView.findViewById(R.id.sensor_name); | |
mDateStepCountText.setText(mStepCountList.get(position).mDate + " - Total Steps: " + String.valueOf(mStepCountList.get(position).mStepCount)); | |
return convertView; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import androidx.appcompat.app.AppCompatActivity; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.view.View; | |
public class MainActivity extends AppCompatActivity { | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
} | |
public void navigateToStepCounterActivity(View v) { | |
Intent mIntent = new Intent(this, StepsCounterActivity.class); | |
startActivity(mIntent); | |
} | |
public void navigateToStepHistoryActivity(View v) { | |
Intent mIntent = new Intent(this, StepsHistoryActivity.class); | |
startActivity(mIntent); | |
} | |
public void navigateToCustomAlgoActivity(View v) { | |
Intent mIntent = new Intent(this, CustomAlgoResultsActivity.class); | |
startActivity(mIntent); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.content.Context; | |
import android.hardware.Sensor; | |
import android.hardware.SensorEvent; | |
import android.hardware.SensorEventListener; | |
import android.hardware.SensorManager; | |
import android.os.Bundle; | |
import android.widget.TextView; | |
import androidx.appcompat.app.AppCompatActivity; | |
public class StepsCounterActivity extends AppCompatActivity implements SensorEventListener { | |
private SensorManager mSensorManager; | |
private Sensor mSensor; | |
private boolean isSensorPresent; | |
private TextView mStepsSinceReboot; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.stepcounter_layout); | |
mStepsSinceReboot = (TextView) findViewById(R.id.stepssincereboot); | |
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE); | |
if (mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) != null) { | |
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); | |
isSensorPresent = true; | |
} else { | |
isSensorPresent = false; | |
} | |
} | |
@Override | |
protected void onResume() { | |
super.onResume(); | |
if (isSensorPresent) { | |
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL); | |
} | |
} | |
@Override | |
protected void onPause() { | |
super.onPause(); | |
if (isSensorPresent) { | |
mSensorManager.unregisterListener(this); | |
} | |
} | |
@Override | |
public void onSensorChanged(SensorEvent event) { | |
mStepsSinceReboot.setText("Steps since reboot:" + String.valueOf(event.values[0])); | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int accuracy) { | |
} | |
@Override | |
protected void onDestroy() { | |
super.onDestroy(); | |
mSensorManager = null; | |
mSensor = null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.content.ContentValues; | |
import android.content.Context; | |
import android.database.Cursor; | |
import android.database.sqlite.SQLiteDatabase; | |
import android.database.sqlite.SQLiteOpenHelper; | |
import java.util.ArrayList; | |
import java.util.Calendar; | |
public class StepsDBHelper extends SQLiteOpenHelper { | |
private static final int DATABASE_VERSION = 1; | |
private static final String DATABASE_NAME = "StepsDatabase"; | |
private static final String TABLE_STEPS_SUMMARY = "StepsSummary"; | |
private static final String ID = "id"; | |
private static final String STEPS_COUNT = "stepscount"; | |
private static final String CREATION_DATE = "creationdate"; | |
private static final String CREATE_TABLE_STEPS_SUMMARY = "CREATE TABLE " | |
+ TABLE_STEPS_SUMMARY + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + | |
CREATION_DATE + " TEXT," + STEPS_COUNT + " INTEGER" + ")"; | |
@Override | |
public void onCreate(SQLiteDatabase db) { | |
db.execSQL(CREATE_TABLE_STEPS_SUMMARY); | |
} | |
public boolean createStepsEntry() { | |
boolean isDateAlreadyPresent = false; | |
boolean createSuccessful = false; | |
int currentDateStepCounts = 0; | |
Calendar mCalendar = Calendar.getInstance(); | |
String todayDate = String.valueOf(mCalendar.get(Calendar.MONTH)) + "/" + | |
String.valueOf(mCalendar.get(Calendar.DAY_OF_MONTH) + 1) + "/" + String.valueOf(mCalendar.get(Calendar.YEAR)); | |
String selectQuery = "SELECT " + STEPS_COUNT + " FROM " + | |
TABLE_STEPS_SUMMARY + " WHERE " + CREATION_DATE + " = '" + todayDate + "'"; | |
try { | |
SQLiteDatabase db = this.getReadableDatabase(); | |
Cursor c = db.rawQuery(selectQuery, null); | |
if (c.moveToFirst()) { | |
do { | |
isDateAlreadyPresent = true; | |
currentDateStepCounts = c.getInt((c.getColumnIndex(STEPS_COUNT))); | |
} while (c.moveToNext()); | |
} | |
db.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
try { | |
SQLiteDatabase db = this.getWritableDatabase(); | |
ContentValues values = new ContentValues(); | |
values.put(CREATION_DATE, todayDate); | |
if (isDateAlreadyPresent) { | |
values.put(STEPS_COUNT, ++currentDateStepCounts); | |
int row = db.update(TABLE_STEPS_SUMMARY, values, CREATION_DATE + " = '" + todayDate + "'", null); | |
if (row == 1) { | |
createSuccessful = true; | |
} | |
db.close(); | |
} else { | |
values.put(STEPS_COUNT, 1); | |
long row = db.insert(TABLE_STEPS_SUMMARY, null, values); | |
if (row != -1) { | |
createSuccessful = true; | |
} | |
db.close(); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return createSuccessful; | |
} | |
public ArrayList<DateStepsModel> readStepsEntries() { | |
ArrayList<DateStepsModel> mStepCountList = new ArrayList<DateStepsModel>(); | |
String selectQuery = "SELECT * FROM " + TABLE_STEPS_SUMMARY; | |
try { | |
SQLiteDatabase db = this.getReadableDatabase(); | |
Cursor c = db.rawQuery(selectQuery, null); | |
if (c.moveToFirst()) { | |
do { | |
DateStepsModel mDateStepsModel = new DateStepsModel(); | |
mDateStepsModel.mDate = c.getString((c.getColumnIndex(CREATION_DATE))); | |
mDateStepsModel.mStepCount = c.getInt((c.getColumnIndex(STEPS_COUNT))); | |
mStepCountList.add(mDateStepsModel); | |
} while (c.moveToNext()); | |
} | |
db.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return mStepCountList; | |
} | |
@Override | |
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { | |
db.execSQL("DROP TABLE IF EXISTS " + CREATE_TABLE_STEPS_SUMMARY); | |
this.onCreate(db); | |
} | |
public StepsDBHelper(Context context) { | |
super(context, DATABASE_NAME, null, DATABASE_VERSION); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.widget.ListView; | |
import androidx.appcompat.app.AppCompatActivity; | |
import java.util.ArrayList; | |
public class StepsHistoryActivity extends AppCompatActivity { | |
StepsDBHelper mStepsDBHelper; | |
ListView mSensorListView; | |
ListAdapter mListAdapter; | |
ArrayList<DateStepsModel> mStepCountList; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.pedometerlist_layout); | |
mSensorListView = (ListView) findViewById(R.id.steps_list); | |
getDataForList(); | |
mListAdapter = new ListAdapter(mStepCountList, this); | |
mSensorListView.setAdapter(mListAdapter); | |
Intent stepsIntent = new Intent(getApplicationContext(), StepsService.class); | |
startService(stepsIntent); | |
} | |
public void getDataForList() { | |
mStepsDBHelper = new StepsDBHelper(this); | |
mStepCountList = mStepsDBHelper.readStepsEntries(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.app.Service; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.hardware.Sensor; | |
import android.hardware.SensorEvent; | |
import android.hardware.SensorEventListener; | |
import android.hardware.SensorManager; | |
import android.os.IBinder; | |
public class StepsService extends Service implements SensorEventListener { | |
SensorManager mSensorManager; | |
Sensor mStepDetectorSensor; | |
StepsDBHelper mStepsDBHelper; | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE); | |
if (mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) != null) { | |
mStepDetectorSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR); | |
mSensorManager.registerListener(this, mStepDetectorSensor, SensorManager.SENSOR_DELAY_NORMAL); | |
mStepsDBHelper = new StepsDBHelper(getApplicationContext()); | |
} | |
} | |
@Override | |
public int onStartCommand(Intent intent, int flags, int startId) { | |
return Service.START_STICKY; | |
} | |
@Override | |
public void onSensorChanged(SensorEvent event) { | |
mStepsDBHelper.createStepsEntry(); | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int accuracy) { | |
} | |
@Override | |
public IBinder onBind(Intent intent) { | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.content.ContentValues; | |
import android.content.Context; | |
import android.database.Cursor; | |
import android.database.sqlite.SQLiteDatabase; | |
import android.database.sqlite.SQLiteOpenHelper; | |
import java.util.ArrayList; | |
import java.util.Calendar; | |
public class StepsTrackerDBHelper extends SQLiteOpenHelper { | |
private static final String DATABASE_NAME = "StepsTrackerDatabase"; | |
private static final String TABLE_STEPS_SUMMARY = "StepsTrackerSummary"; | |
private static final String ID = "id"; | |
private static final String STEP_TYPE = "steptype"; | |
private static final String STEP_TIME = "steptime";//time is in milliseconds Epoch Time | |
private static final String STEP_DATE = "stepdate";//Date format is mm/dd/yyyy | |
private static final String SESSION_ID = "sessionid"; | |
private static final String CREATE_TABLE_STEPS_SUMMARY = "CREATE TABLE " | |
+ TABLE_STEPS_SUMMARY + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + STEP_DATE + " TEXT," + SESSION_ID + " TEXT," + STEP_TIME + " INTEGER," + STEP_TYPE + " TEXT" + ")"; | |
public boolean createStepsEntry(long timeStamp, int stepType, String sessionId) { | |
boolean createSuccessful = false; | |
Calendar mCalendar = Calendar.getInstance(); | |
String todayDate = String.valueOf(mCalendar.get(Calendar.MONTH) + 1) + "/" + String.valueOf(mCalendar.get(Calendar.DAY_OF_MONTH)) + "/" + String.valueOf(mCalendar.get(Calendar.YEAR)); | |
try { | |
SQLiteDatabase db = this.getWritableDatabase(); | |
ContentValues values = new ContentValues(); | |
values.put(STEP_TIME, timeStamp); | |
values.put(STEP_DATE, todayDate); | |
values.put(STEP_TYPE, stepType); | |
values.put(SESSION_ID, sessionId); | |
long row = db.insert(TABLE_STEPS_SUMMARY, null, values); | |
if (row != -1) { | |
createSuccessful = true; | |
} | |
db.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return createSuccessful; | |
} | |
public int[] getStepsByDate(String date) { | |
int stepType[] = new int[3]; | |
String selectQuery = "SELECT " + STEP_TYPE + " FROM " + TABLE_STEPS_SUMMARY + " WHERE " + STEP_DATE + " = '" + date + "'"; | |
try { | |
SQLiteDatabase db = this.getReadableDatabase(); | |
Cursor c = db.rawQuery(selectQuery, null); | |
if (c.moveToFirst()) { | |
do { | |
switch (c.getInt((c.getColumnIndex(STEP_TYPE)))) { | |
case WALKING: | |
++stepType[0]; | |
break; | |
case JOGGING: | |
++stepType[1]; | |
break; | |
case RUNNING: | |
++stepType[2]; | |
break; | |
} | |
} while (c.moveToNext()); | |
} | |
db.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return stepType; | |
} | |
//For Debug Purposes | |
public long getTotalStepsDuration() { | |
long totalDuration = 0; | |
ArrayList<String> sessionNameList = new ArrayList<String>(); | |
ArrayList<Integer> stepTimeSessionList = new ArrayList<Integer>(); | |
try { | |
String selectQuery = "SELECT DISTINCT" + SESSION_ID + " FROM " + TABLE_STEPS_SUMMARY; | |
SQLiteDatabase db = this.getReadableDatabase(); | |
Cursor c = db.rawQuery(selectQuery, null); | |
if (c.moveToFirst()) { | |
do { | |
sessionNameList.add(c.getString((c.getColumnIndex(SESSION_ID)))); | |
} while (c.moveToNext()); | |
} | |
int sizeSessionNameList = sessionNameList.size(); | |
for (int i = 0; i < sizeSessionNameList; i++) { | |
String selectTimeQuery = "SELECT " + STEP_TIME + " FROM " + TABLE_STEPS_SUMMARY + " WHERE " + SESSION_ID + " = '" + sessionNameList.get(i) + "'"; | |
Cursor cTime = db.rawQuery(selectTimeQuery, null); | |
if (cTime.moveToFirst()) { | |
do { | |
stepTimeSessionList.add(cTime.getInt((cTime.getColumnIndex(STEP_TIME)))); | |
} while (cTime.moveToNext()); | |
} | |
int sizeStepTimeSessionList = stepTimeSessionList.size(); | |
for (int j = sizeStepTimeSessionList - 1; j == 1; j--) { | |
totalDuration = totalDuration + stepTimeSessionList.get(j) - stepTimeSessionList.get(j - 1); | |
} | |
} | |
db.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return totalDuration; | |
} | |
//For Debug Purposes | |
public ArrayList<String> getAvailableDates() { | |
ArrayList<String> dateList = new ArrayList<String>(); | |
try { | |
String selectQuery = "SELECT DISTINCT" + STEP_DATE + " FROM " + TABLE_STEPS_SUMMARY; | |
SQLiteDatabase db = this.getReadableDatabase(); | |
Cursor c = db.rawQuery(selectQuery, null); | |
if (c.moveToFirst()) { | |
do { | |
dateList.add(c.getString((c.getColumnIndex(STEP_DATE)))); | |
} while (c.moveToNext()); | |
} | |
db.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return dateList; | |
} | |
private static final int DATABASE_VERSION = 1; | |
private static final int RUNNING = 3; | |
private static final int JOGGING = 2; | |
private static final int WALKING = 1; | |
@Override | |
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { | |
db.execSQL("DROP TABLE IF EXISTS " + CREATE_TABLE_STEPS_SUMMARY); | |
this.onCreate(db); | |
} | |
public StepsTrackerDBHelper(Context context) { | |
super(context, DATABASE_NAME, null, DATABASE_VERSION); | |
} | |
@Override | |
public void onCreate(SQLiteDatabase db) { | |
db.execSQL(CREATE_TABLE_STEPS_SUMMARY); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.pedometer; | |
import android.app.Service; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.hardware.Sensor; | |
import android.hardware.SensorEvent; | |
import android.hardware.SensorEventListener; | |
import android.hardware.SensorManager; | |
import android.os.IBinder; | |
import android.os.SystemClock; | |
import java.util.ArrayList; | |
import java.util.Calendar; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ScheduledExecutorService; | |
import java.util.concurrent.ScheduledFuture; | |
import java.util.concurrent.TimeUnit; | |
public class StepsTrackerService extends Service { | |
private SensorManager mSensorManager; | |
private Sensor mStepDetectorSensor; | |
private Sensor mAccelerometerSensor; | |
private AccelerometerListener mAccelerometerListener; | |
private StepDetectorListener mStepDetectorListener; | |
private StepsTrackerDBHelper mStepsTrackerDBHelper; | |
private static final int WALKINGPEAK = 18; | |
private static final int JOGGINGPEAK = 25; | |
private static final int RUNNINGPEAK = 32; | |
private static final int RUNNING = 3; | |
private static final int JOGGING = 2; | |
private static final int WALKING = 1; | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE); | |
if (mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) != null) { | |
mStepDetectorSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR); | |
mStepDetectorListener = new StepDetectorListener(); | |
mSensorManager.registerListener((SensorEventListener) mStepDetectorListener, mStepDetectorSensor, SensorManager.SENSOR_DELAY_FASTEST); | |
} | |
if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) { | |
mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); | |
} | |
mStepsTrackerDBHelper = new StepsTrackerDBHelper(this); | |
} | |
ScheduledExecutorService mScheduledExecutorService = Executors.newScheduledThreadPool(2); | |
private ScheduledFuture mScheduledUnregisterAccelerometerTask; | |
private ScheduledFuture mScheduledProcessDataTask; | |
private UnregisterAcceleromterTask mUnregisterAcceleromterTask; | |
private ProcessDataTask mProcessDataTask; | |
private boolean isScheduleUnregistered = false; | |
private boolean isAccelerometerRegistered = false; | |
private String sessionId; | |
class StepDetectorListener implements SensorEventListener { | |
@Override | |
public void onSensorChanged(SensorEvent event) { | |
if (!isAccelerometerRegistered && mAccelerometerSensor != null) { | |
mAccelerometerListener = new AccelerometerListener(); | |
mSensorManager.registerListener(mAccelerometerListener, mAccelerometerSensor, SensorManager.SENSOR_DELAY_FASTEST); | |
sessionId = Calendar.getInstance().getTime().toLocaleString(); | |
isAccelerometerRegistered = true; | |
} | |
if (isScheduleUnregistered) { | |
mScheduledUnregisterAccelerometerTask.cancel(true); | |
} | |
mUnregisterAcceleromterTask = new UnregisterAcceleromterTask(); | |
mScheduledUnregisterAccelerometerTask = mScheduledExecutorService.schedule(mUnregisterAcceleromterTask, 20000, TimeUnit.MILLISECONDS); | |
isScheduleUnregistered = true; | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int accuracy) { | |
} | |
} | |
class UnregisterAcceleromterTask implements Runnable { | |
@Override | |
public void run() { | |
isAccelerometerRegistered = false; | |
mSensorManager.unregisterListener(mAccelerometerListener); | |
isScheduleUnregistered = false; | |
mScheduledProcessDataTask.cancel(false); | |
} | |
} | |
private long timeOffsetValue; | |
ArrayList<AccelerometerData> mAccelerometerDataList = new ArrayList<AccelerometerData>(); | |
ArrayList<AccelerometerData> mRawDataList = new ArrayList<AccelerometerData>(); | |
ArrayList<AccelerometerData> mAboveThresholdValuesList = new ArrayList<AccelerometerData>(); | |
ArrayList<AccelerometerData> mHighestPeakList = new ArrayList<AccelerometerData>(); | |
class AccelerometerListener implements SensorEventListener { | |
public AccelerometerListener() { | |
mProcessDataTask = new ProcessDataTask(); | |
mScheduledProcessDataTask = mScheduledExecutorService.scheduleWithFixedDelay(mProcessDataTask, 10000, 10000, TimeUnit.MILLISECONDS); | |
} | |
@Override | |
public void onSensorChanged(SensorEvent event) { | |
AccelerometerData mAccelerometerData = new AccelerometerData(); | |
mAccelerometerData.x = event.values[0]; | |
mAccelerometerData.y = event.values[1]; | |
mAccelerometerData.z = event.values[2]; | |
mAccelerometerData.time = event.timestamp; | |
mAccelerometerDataList.add(mAccelerometerData); | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int accuracy) { | |
} | |
} | |
class ProcessDataTask implements Runnable { | |
@Override | |
public void run() { | |
//Copy accelerometer data from main sensor array in separate array for processing | |
mRawDataList.addAll(mAccelerometerDataList); | |
mAccelerometerDataList.clear(); | |
//Calculating the magnitude (Square root of sum of squares of x, y, z) & converting time from nano seconds from boot time to epoc time | |
timeOffsetValue = System.currentTimeMillis() - SystemClock.elapsedRealtime(); | |
int dataSize = mRawDataList.size(); | |
for (int i = 0; i < dataSize; i++) { | |
mRawDataList.get(i).value = Math.sqrt(Math.pow(mRawDataList.get(i).x, 2) + Math.pow(mRawDataList.get(i).y, 2) + Math.pow(mRawDataList.get(i).z, 2)); | |
mRawDataList.get(i).time = (mRawDataList.get(i).time / 1000000L) + timeOffsetValue; | |
} | |
//Calculating the High Peaks | |
findHighPeaks(); | |
//Remove high peaks close to each other which are within range of 0.4 seconds | |
removeClosePeaks(); | |
//Find the type of step (Running, jogging, walking) & store in Database | |
findStepTypeAndStoreInDB(); | |
mRawDataList.clear(); | |
mAboveThresholdValuesList.clear(); | |
mHighestPeakList.clear(); | |
} | |
public void findHighPeaks() { | |
//Calculating the High Peaks | |
boolean isAboveMeanLastValueTrue = false; | |
int dataSize = mRawDataList.size(); | |
for (int i = 0; i < dataSize; i++) { | |
if (mRawDataList.get(i).value > WALKINGPEAK) { | |
mAboveThresholdValuesList.add(mRawDataList.get(i)); | |
isAboveMeanLastValueTrue = false; | |
} else { | |
if (!isAboveMeanLastValueTrue && mAboveThresholdValuesList.size() > 0) { | |
Collections.sort(mAboveThresholdValuesList, new DataSorter()); | |
mHighestPeakList.add(mAboveThresholdValuesList.get(mAboveThresholdValuesList.size() - 1)); | |
mAboveThresholdValuesList.clear(); | |
} | |
isAboveMeanLastValueTrue = true; | |
} | |
} | |
} | |
public void removeClosePeaks() { | |
for (int i = 0; i < mHighestPeakList.size() - 1; i++) { | |
if (mHighestPeakList.get(i).isRealPeak) { | |
if (mHighestPeakList.get(i + 1).time - mHighestPeakList.get(i).time < 400) { | |
if (mHighestPeakList.get(i + 1).value > mHighestPeakList.get(i).value) { | |
mHighestPeakList.get(i).isRealPeak = false; | |
} else { | |
mHighestPeakList.get(i + 1).isRealPeak = false; | |
} | |
} | |
} | |
} | |
} | |
public void findStepTypeAndStoreInDB() { | |
int size = mHighestPeakList.size(); | |
for (int i = 0; i < size; i++) { | |
if (mHighestPeakList.get(i).isRealPeak) { | |
if (mHighestPeakList.get(i).value > RUNNINGPEAK) { | |
mStepsTrackerDBHelper.createStepsEntry(mHighestPeakList.get(i).time, RUNNING, sessionId); | |
} else { | |
if (mHighestPeakList.get(i).value > JOGGINGPEAK) { | |
mStepsTrackerDBHelper.createStepsEntry(mHighestPeakList.get(i).time, JOGGING, sessionId); | |
} else { | |
mStepsTrackerDBHelper.createStepsEntry(mHighestPeakList.get(i).time, WALKING, sessionId); | |
} | |
} | |
} | |
} | |
} | |
public class DataSorter implements Comparator<AccelerometerData> { | |
public int compare(AccelerometerData obj1, AccelerometerData obj2) { | |
int returnVal = 0; | |
if (obj1.value < obj2.value) { | |
returnVal = -1; | |
} else if (obj1.value > obj2.value) { | |
returnVal = 1; | |
} | |
return returnVal; | |
} | |
} | |
} | |
@Override | |
public IBinder onBind(Intent intent) { | |
return null; | |
} | |
@Override | |
public int onStartCommand(Intent intent, int flags, int startId) { | |
return Service.START_STICKY; | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
mScheduledExecutorService.shutdown(); | |
} | |
} |
0 Comments