edu.missouri.bas.service.SensorService.java Source code

Java tutorial

Introduction

Here is the source code for edu.missouri.bas.service.SensorService.java

Source

package edu.missouri.bas.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;

import edu.missouri.bas.MainActivity;
import edu.missouri.bas.R;
import edu.missouri.bas.SensorConnections;
import edu.missouri.bas.SurveyStatus;
import edu.missouri.bas.bluetooth.BluetoothRunnable;
import edu.missouri.bas.bluetooth.affectiva.AffectivaPacket;
import edu.missouri.bas.bluetooth.affectiva.AffectivaRunnable;
import edu.missouri.bas.bluetooth.equivital.EquivitalRunnable;
import edu.missouri.bas.datacollection.InternalSensor;
import edu.missouri.bas.service.modules.location.ActivityRecognitionScan;
import edu.missouri.bas.service.modules.location.DetectionRemover;
import edu.missouri.bas.service.modules.location.LocationControl;
import edu.missouri.bas.service.modules.sensors.SensorControl;
import edu.missouri.bas.survey.XMLSurveyActivity;
import edu.missouri.bas.survey.XMLSurveyActivity.StartSound;
import edu.missouri.bas.survey.answer.SurveyAnswer;
import android.R.string;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.equivital.sdk.connection.SemBluetoothConnection;
import com.equivital.sdk.decoder.SDKLicense;
import com.equivital.sdk.decoder.SemDevice;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.ActivityRecognitionClient;
import com.google.android.gms.location.DetectedActivity;
import com.google.android.gms.location.LocationClient;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

//Ricky 2013/12/09
import android.os.AsyncTask;

public class SensorService extends Service implements GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener {

    private final String TAG = "SensorService";
    /*
     * Android component variables used by the service
     */
    public static Context serviceContext;
    private IBinder mBinder = new ServiceBinder<SensorService>(SensorService.this);

    /*
     * Notification variables
     */
    private NotificationManager notificationManager;
    private Notification notification;

    /*
     * Sensor variables
     */
    private LocationManager mLocationManager;
    private SensorManager mSensorManager;
    private SensorEventListener mSensorListener;
    private long stime;
    private SensorControl sensorControl = null;
    private static LocationControl locationControl = null;

    /*
     * File I/O Variables 
     */
    public final static String BASE_PATH = "sdcard/TestResults/";
    public String PATH_TOREAD;
    //public static File BASE_PATH;
    private final String[] surveyNames = { "CRAVING_EPISODE", "DRINKING_FOLLOWUP", "MORNING_REPORT",
            "RANDOM_ASSESSMENT", "MOOD_DYSREGULATION", "INITIAL_DRINKING" };
    private HashMap<String, String> surveyFiles;

    PowerManager mPowerManager;
    WakeLock serviceWakeLock;

    /*
     * Alarm manager variables, for scheduling intents
     */
    public static AlarmManager mAlarmManager;
    private PendingIntent scheduleSurvey;
    private PendingIntent drinkfollowupSurvey;
    //private static PendingIntent scheduleLocation;
    private static PendingIntent scheduleCheck;
    private static PendingIntent triggerSound;
    private static PendingIntent triggerSound2;
    //private PendingIntent surveyIntent;

    /*
     * Static intent actions
     */
    public static final String ACTION_SCHEDULE_SURVEY = "INTENT_ACTION_SCHEDULE_SURVEY";

    public static final String ACTION_SCHEDULE_SENSOR = "INTENT_ACTION_SCHEDULE_SENSOR";

    public static final String ACTION_SCHEDULE_LOCATION = "INTENT_ACTION_SCHEDULE_LOCATION";

    public static final String ACTION_START_SENSORS = "INTENT_ACTION_START_SENSORS";

    public static final String ACTION_STOP_LOCATIONCONTROL = "INTENT_ACTION_STOP_LOCATIONCONTROL";

    public static final String ACTION_SENSOR_DATA = "INTENT_ACTION_SENSOR_DATA";

    private static final String ACTION_TRIGGER_SOUND = "INTENT_ACTION_TRIGGER_SOUND";

    private static final String ACTION_TRIGGER_SOUND2 = "INTENT_ACTION_TRIGGER_SOUND2";

    private static final String ACTION_SCHEDULE_CHECK = "INTENT_ACTION_SCHEDULE_CHECK";

    public static final String ACTION_TRIGGER_SURVEY = "INTENT_ACTION_TRIGGER_SURVEY";

    public static final String ACTION_START_SOUND = "INTENT_ACTION_START_SOUND";

    public static final String ACTION_CONNECT_BLUETOOTH = "INTENT_ACTION_CONNECT_BLUETOOTH";

    public static final String ACTION_DISCONNECT_BLUETOOTH = "INTENT_ACTION_DISCONNECT_BLUETOOTH";

    public static final String ACTION_GET_BLUETOOTH_STATE = "INTENT_ACTION_BLUETOOTH_STATE";

    public static final String ACTION_BLUETOOTH_RESULT = "INTENT_ACTION_BLUETOOTH_RESULT";

    public static final String ACTION_BLUETOOTH_STATE_RESULT = "INTENT_ACTION_BLUETOOTH_STATE_RESULT";

    public static final String ACTION_RECONNECT_CHESTSENSOR = "INTENT_ACTION_RECONNECT_CHESTSENSOR";

    public static final String ACTION_START_RECONNECTING = "INTENT_ACTION_START_RECONNECTING";

    public static final String INTENT_EXTRA_BT_DEVICE = "EXTRA_DEVICE_ADR";

    public static final String INTENT_EXTRA_BT_MODE = "EXTRA_DEVICE_MODE";

    public static final String INTENT_EXTRA_BT_TYPE = "EXTRA_DEVICE_TYPE";

    public static final String INTENT_EXTRA_BT_UUID = "EXTRA_DEVICE_UUID";

    public static final String INTENT_EXTRA_BT_RESULT = "EXTRA_BLUETOOTH_RESULT";

    public static final String INTENT_EXTRA_BT_STATE = "EXTRA_BLUETOOTH_STATE";

    public static final String INTENT_EXTRA_BT_DEVICE_NAME = null;

    public static final String INTENT_EXTRA_BT_DEVICE_ADDRESS = null;

    public static final int MESSAGE_BLUETOOTH_DATA = 0;

    public static final int MESSAGE_LOCATION_DATA = 1;

    public static final int MESSAGE_SENSOR_DATA = 3;

    public static final String Listening = "Listening";

    public static final String ACTION_CONNECT_CHEST = "INTENT_ACTION_CONNECT_CHEST";

    public static final String KEY_ADDRESS = "KEY_ADDRESS";

    public static final int CHEST_SENSOR_DATA = 109;

    public static final String START_HOUR = "START_HOUR";

    public static final String END_HOUR = "END_HOUR";

    public static final String START_MIN = "START_MIN";

    public static final String END_MIN = "END_MIN";

    static String errMSG = "Please check your wifi or dataplan.\r\nThe phone is offline now.";

    static boolean IsScheduled = false;

    boolean mExternalStorageAvailable = false;

    boolean mExternalStorageWriteable = false;

    //ADD ACTION STRING FOR DRINKING-FOLLOWUP
    public static final String ACTION_DRINK_FOLLOWUP = "INTENT_ACTION_DRINK_FOLLOWUP";

    public static Timer t1 = new Timer();
    public static Timer t2 = new Timer();
    public static Timer t3 = new Timer();
    public static Timer t4 = new Timer();
    public static Timer t5 = new Timer();
    public static Timer t6 = new Timer();

    //Ricky 2013/12/10
    //ADD TIMER FOR THE DRINK-FOLLOW TIMER
    public static Timer t7 = new Timer();
    //Add count to stop the timer tasks
    private static int dCount = 1;
    //Flag for detecting whether there is still some drinkingfollowup being scheduled
    private static boolean dFlag = false;
    //static var for DrinkSurvey task;
    private static TimerTask drinkSurveyTask;
    //variable to detect whether the drinking follow-up survey is on the top 
    public static Boolean drinkUpFlag = false;
    //Add Four TimerTask var for drink-survey so later we could cancel the task instead of canceling the timer
    public static TimerTask alarmTask1;
    public static TimerTask alarmTask2;
    public static TimerTask alarmTask3;
    public static TimerTask alarmTask4;
    //Add Four TimerTask var for ramdom survey so later we could cancel the task instead of canceling the timer
    public static TimerTask rTask1;
    public static TimerTask rTask2;
    public static TimerTask rTask3;
    public static TimerTask rTask4;
    public static TimerTask rTask5;
    public static TimerTask rTask6;
    //Add one Timer
    public static Timer alarmTimer = new Timer();

    /*
     * Bluetooth Variables
     */
    Thread bluetoothThread;
    AffectivaRunnable affectivaRunnable;
    String bluetoothMacAddress = "default";
    BluetoothAdapter mBluetoothAdapter;

    /*
     * Worker Threads
     */
    Thread httpPostThread;
    Thread FileWriterThread;
    HttpPostThread httpPostRunnable;
    Runnable fileWriterRunnable;
    InternalSensor Accelerometer;
    InternalSensor LightSensor;
    InternalSensor Pressure;
    EquivitalRunnable equivitalThread;
    Notification mainServiceNotification;
    public static final int SERVICE_NOTIFICATION_ID = 1;

    private static SemDevice device;

    //Variables for storing chest sensor values

    ActivityRecognitionScan activityRecognition;
    DetectionRemover mDetectionRemover;
    public static int currentUserActivity = 9;
    public static boolean IsRetrievingUpdates = false;
    LocationClient mLocationClient;

    private SoundPool mSoundPool;
    private int SOUND1 = 1;
    private int SOUND2 = 2;
    private HashMap<Integer, Integer> soundsMap;
    /*public StartSound ss;
    public StartSound2 ss2;
    public static StartSound mSound1;
    public static StartSound2 mSound2;*/
    //static Timer mTimer;
    int reconnectionAttempts = 0;

    /*
     * (non-Javadoc)
     * @see android.app.Service#onBind(android.content.Intent)
     */
    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate() {

        super.onCreate();
        Log.d(TAG, "Starting sensor service");
        mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
        soundsMap = new HashMap<Integer, Integer>();
        soundsMap.put(SOUND1, mSoundPool.load(this, R.raw.bodysensor_alarm, 1));
        soundsMap.put(SOUND2, mSoundPool.load(this, R.raw.voice_notification, 1));

        serviceContext = this;

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        bluetoothMacAddress = mBluetoothAdapter.getAddress();
        mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        //Get location manager
        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        activityRecognition = new ActivityRecognitionScan(getApplicationContext());
        activityRecognition.startActivityRecognitionScan();

        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);

        serviceWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SensorServiceLock");
        serviceWakeLock.acquire();

        //Initialize start time
        stime = System.currentTimeMillis();

        //Setup calendar object
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(stime);

        /*
         * Setup notification manager
         */

        notification = new Notification(R.drawable.icon2, "Recorded", System.currentTimeMillis());
        notification.defaults = 0;
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        Intent notifyIntent = new Intent(Intent.ACTION_MAIN);
        notifyIntent.setClass(this, MainActivity.class);

        /*
         * Display notification that service has started
         */
        notification.tickerText = "Sensor Service Running";
        PendingIntent contentIntent = PendingIntent.getActivity(SensorService.this, 0, notifyIntent,
                Notification.FLAG_ONGOING_EVENT);
        notification.setLatestEventInfo(SensorService.this, getString(R.string.app_name),
                "Recording service started at: " + cal.getTime().toString(), contentIntent);

        notificationManager.notify(SensorService.SERVICE_NOTIFICATION_ID, notification);

        // locationControl = new LocationControl(this, mLocationManager, 1000 * 60, 200, 5000);   

        IntentFilter activityResultFilter = new IntentFilter(XMLSurveyActivity.INTENT_ACTION_SURVEY_RESULTS);
        SensorService.this.registerReceiver(alarmReceiver, activityResultFilter);

        IntentFilter sensorDataFilter = new IntentFilter(SensorService.ACTION_SENSOR_DATA);
        SensorService.this.registerReceiver(alarmReceiver, sensorDataFilter);
        Log.d(TAG, "Sensor service created.");

        try {
            prepareIO();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        prepareAlarms();

        Intent startSensors = new Intent(SensorService.ACTION_START_SENSORS);
        this.sendBroadcast(startSensors);

        Intent scheduleCheckConnection = new Intent(SensorService.ACTION_SCHEDULE_CHECK);
        scheduleCheck = PendingIntent.getBroadcast(serviceContext, 0, scheduleCheckConnection, 0);
        mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime() + 1000 * 60 * 5, 1000 * 60 * 5, scheduleCheck);
        mLocationClient = new LocationClient(this, this, this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub   
        mLocationClient.connect();
        return START_NOT_STICKY;
    }

    BroadcastReceiver checkRequestReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context arg0, Intent intent) {
            // TODO Auto-generated method stub
            String action = intent.getAction();
            Log.d(TAG, "Check Request Recieved");
            //int state=SemBluetoothConnection.getState();         
            if (action.equals(SensorService.ACTION_SCHEDULE_CHECK)) {

                Runtime info = Runtime.getRuntime();
                long freeSize = info.freeMemory();
                long totalSize = info.totalMemory();
                long usedSize = totalSize - freeSize;
                double temp = freeSize / (double) totalSize;
                DecimalFormat percentFormat = new DecimalFormat("#.#%");
                Calendar c = Calendar.getInstance();
                SimpleDateFormat curFormater = new SimpleDateFormat("MMMMM_dd");
                String dateObj = curFormater.format(c.getTime());
                String file_name = "MemoryUsage_" + dateObj + ".txt";
                Calendar cal = Calendar.getInstance();
                cal.setTimeZone(TimeZone.getTimeZone("US/Central"));

                File f = new File(BASE_PATH, file_name);
                String dataToWrite = String.valueOf(cal.getTime()) + "," + String.valueOf(usedSize / 1024) + ","
                        + String.valueOf(totalSize / 1024) + "," + String.valueOf(freeSize / 1024) + ","
                        + String.valueOf(percentFormat.format(temp));

                if (f != null) {
                    try {
                        writeToFile(f, dataToWrite);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else if (action.equals(SensorService.ACTION_START_SENSORS)) {
                sensorThread.run();
            }
        }

    };

    private Runnable sensorThread = new Runnable() {
        public void run() {
            Accelerometer = new InternalSensor(mSensorManager, Sensor.TYPE_ACCELEROMETER,
                    SensorManager.SENSOR_DELAY_NORMAL, bluetoothMacAddress);
            Accelerometer.run();
            LightSensor = new InternalSensor(mSensorManager, Sensor.TYPE_LIGHT, SensorManager.SENSOR_DELAY_NORMAL,
                    bluetoothMacAddress);
            LightSensor.run();
        }
    };

    BroadcastReceiver soundRequestReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context arg0, Intent intent) {
            // TODO Auto-generated method stub
            String action = intent.getAction();
            if (action.equals(SensorService.ACTION_START_SOUND)) {
                Log.d(TAG, "Task Scheduled to run Sound Effects");
                startSound();
            } else if (action.equals(SensorService.ACTION_TRIGGER_SOUND)) {
                playSound(1, 1.0f);
                Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                v.vibrate(1000);
            } else if (action.equals(SensorService.ACTION_TRIGGER_SOUND2)) {
                playSound(2, 1.0f);
            }

        }

    };

    public void startSound() {

        Intent scheduleTriggerSound = new Intent(SensorService.ACTION_TRIGGER_SOUND);
        Intent scheduleTriggerSound2 = new Intent(SensorService.ACTION_TRIGGER_SOUND2);
        triggerSound = PendingIntent.getBroadcast(serviceContext, 0, scheduleTriggerSound, 0);
        triggerSound2 = PendingIntent.getBroadcast(serviceContext, 0, scheduleTriggerSound2, 0);
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000, triggerSound);
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000 * 20,
                triggerSound2);

    }

    public class ConnectSensor extends TimerTask {
        String mAddress;

        public ConnectSensor(String Mac_Address) {
            mAddress = Mac_Address;

        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            Intent connectChest = new Intent(SensorService.ACTION_CONNECT_CHEST);
            connectChest.putExtra(SensorService.KEY_ADDRESS, mAddress);
            serviceContext.sendBroadcast(connectChest);
        }

    }

    public void playSound(int sound, float fSpeed) {
        AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
        float volume = streamVolumeCurrent;
        mSoundPool.play(soundsMap.get(sound), volume, volume, 1, 0, fSpeed);

    }

    private void prepareAlarms() {
        IntentFilter locationSchedulerFilter = new IntentFilter(ACTION_SCHEDULE_LOCATION);
        IntentFilter locationInterruptSchedulerFilter = new IntentFilter(ACTION_STOP_LOCATIONCONTROL);
        IntentFilter surveyScheduleFilter = new IntentFilter(ACTION_SCHEDULE_SURVEY);
        IntentFilter surveyTest = new IntentFilter("ACTION_SURVEY_TEST");

        //ADD INTENTFILTER FOR DRINKING-FOLLOWUP
        IntentFilter followUpFilter = new IntentFilter(ACTION_DRINK_FOLLOWUP);

        /*   Intent scheduleLocationIntent = new Intent(SensorService.ACTION_SCHEDULE_LOCATION);
           scheduleLocation = PendingIntent.getBroadcast(
        serviceContext, 0, scheduleLocationIntent, 0);
           mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + 10000, 1000 * 60 * 5, scheduleLocation);*/

        IntentFilter soundRequest = new IntentFilter(ACTION_START_SOUND);
        IntentFilter checkRequest = new IntentFilter(ACTION_SCHEDULE_CHECK);
        IntentFilter startSensors = new IntentFilter(ACTION_START_SENSORS);
        IntentFilter locationFoundFilter = new IntentFilter(LocationControl.INTENT_ACTION_LOCATION);
        IntentFilter sound1 = new IntentFilter(ACTION_TRIGGER_SOUND);
        IntentFilter sound2 = new IntentFilter(ACTION_TRIGGER_SOUND2);
        SensorService.this.registerReceiver(alarmReceiver, locationFoundFilter);
        SensorService.this.registerReceiver(alarmReceiver, locationSchedulerFilter);
        SensorService.this.registerReceiver(alarmReceiver, locationInterruptSchedulerFilter);
        SensorService.this.registerReceiver(alarmReceiver, surveyScheduleFilter);
        SensorService.this.registerReceiver(alarmReceiver, surveyTest);
        //Register the drink-followup to the alarmReceiver
        SensorService.this.registerReceiver(alarmReceiver, followUpFilter);
        SensorService.this.registerReceiver(soundRequestReceiver, soundRequest);
        SensorService.this.registerReceiver(soundRequestReceiver, sound1);
        SensorService.this.registerReceiver(soundRequestReceiver, sound2);
        SensorService.this.registerReceiver(checkRequestReceiver, checkRequest);
        SensorService.this.registerReceiver(checkRequestReceiver, startSensors);
        IntentFilter chestSensorData = new IntentFilter(ACTION_CONNECT_CHEST);
        SensorService.this.registerReceiver(chestSensorReceiver, chestSensorData);
    }

    //Function to trigger random survey
    private class ScheduleSurvey extends TimerTask {
        int TriggerInterval;

        public ScheduleSurvey(int Time) {
            TriggerInterval = Time;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            Log.d("TAG", drinkUpFlag.toString());
            if (drinkUpFlag == false) {
                Random rand = new Random();
                int TriggerTime = rand.nextInt(TriggerInterval) + 1;
                Intent i = new Intent(serviceContext, XMLSurveyActivity.class);
                i.putExtra("survey_name", "RANDOM_ASSESSMENT");
                i.putExtra("survey_file", "RandomAssessmentParcel.xml");
                scheduleSurvey = PendingIntent.getActivity(SensorService.this, 0, i, Intent.FLAG_ACTIVITY_NEW_TASK);
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() + 1000 * 60 * TriggerTime, scheduleSurvey);
            } else {
                this.cancel();
                Log.d(TAG, "Random Survey Canceled due to the drinkSurvey");
            }
        }
    }

    //Function to trigger drinking-followup survey
    private class DrinkSurvey extends TimerTask {
        int TriggerTime;

        public DrinkSurvey() {
            //TriggerTime=30*60*1000;
            //Test
            TriggerTime = 3000;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            //if dFlag is true, it means the drinkingfollow Task is triggered.
            //dFlag = true;
            if ((dCount <= 3)) {
                Intent i = new Intent(serviceContext, XMLSurveyActivity.class);
                i.putExtra("survey_name", "DRINKING_FOLLOWUP");
                i.putExtra("survey_file", "DrinkingFollowup.xml");
                drinkfollowupSurvey = PendingIntent.getActivity(SensorService.this, 0, i,
                        Intent.FLAG_ACTIVITY_NEW_TASK);
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TriggerTime,
                        drinkfollowupSurvey);
                dCount++;
            } else {
                dCount = 1;
                this.cancel();
                //reset the dFlag 
                dFlag = false;
            }
        }
    }

    /*
     * Prepare IO that will be used for different recording tasks
     */
    private void prepareIO() throws IOException {
        surveyFiles = new HashMap<String, String>();

        //If the base directory doesn't exist, create it
        File DIR = new File(BASE_PATH);
        if (!DIR.exists())
            DIR.mkdir();

        Log.d(TAG, "IO Prepared");
    }

    /*
     * Unregister battery receiver and make sure the sensors are done
     * before destroying the service
     * @see android.app.Service#onDestroy()
     */
    @Override
    public void onDestroy() {

        File f = new File(BASE_PATH, "SensorServiceEvents.txt");
        Calendar cal = Calendar.getInstance();
        try {
            writeToFile(f, "Destroyed at " + String.valueOf(cal.getTime()));
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        if (affectivaRunnable != null) {
            affectivaRunnable.stop();
            try {
                bluetoothThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        notificationManager.cancel(SensorService.SERVICE_NOTIFICATION_ID);

        SensorService.this.unregisterReceiver(alarmReceiver);
        SensorService.this.unregisterReceiver(chestSensorReceiver);
        SensorService.this.unregisterReceiver(soundRequestReceiver);
        SensorService.this.unregisterReceiver(checkRequestReceiver);

        //If canceled, it will have some problems. Need to be handled later.
        mAlarmManager.cancel(scheduleSurvey);
        mAlarmManager.cancel(drinkfollowupSurvey);
        //mAlarmManager.cancel(scheduleLocation);   
        mAlarmManager.cancel(scheduleCheck);
        mAlarmManager.cancel(triggerSound);
        mAlarmManager.cancel(triggerSound2);
        mLocationClient.disconnect();
        activityRecognition.stopActivityRecognitionScan();
        Accelerometer.stop();
        LightSensor.stop();

        CancelTask(alarmTask1);
        CancelTask(alarmTask2);
        CancelTask(alarmTask3);
        CancelTask(alarmTask4);
        CancelTask(drinkSurveyTask);
        CancelTask(rTask1);
        CancelTask(rTask2);
        CancelTask(rTask3);
        CancelTask(rTask4);
        CancelTask(rTask5);
        CancelTask(rTask6);
        /*
         * If we try to cancel the timer, when we reuse the timer
         * the system will show error msg
        CancelTimers(t1);
        CancelTimers(t2);
        CancelTimers(t3);
        CancelTimers(t4);
        CancelTimers(t5);
        CancelTimers(t6);
        CancelTimers(t7);
        */
        //CancelTimers(alarmTimer);
        PurgeTimers(t1);
        PurgeTimers(t2);
        PurgeTimers(t3);
        PurgeTimers(t4);
        PurgeTimers(t5);
        PurgeTimers(t6);
        PurgeTimers(t7);
        PurgeTimers(alarmTimer);
        setStatus(false);

        serviceWakeLock.release();

        Log.d(TAG, "Service Stopped.");

        super.onDestroy();
        if (device != null) {
            device.stop();
        }
    }

    BroadcastReceiver alarmReceiver = new BroadcastReceiver() {
        @SuppressWarnings("deprecation")
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (action.equals(SensorService.ACTION_STOP_LOCATIONCONTROL)) {
                Log.d(TAG, "Stoping Location Upates");
            } else if (action.equals(SensorService.ACTION_SCHEDULE_LOCATION)) {
                Log.d(TAG, "Received alarm event - schedule location");
                //locationControl.startRecording();            
                currentUserActivity = intent.getIntExtra("activity", 9);
                Location mCurrentLocation = mLocationClient.getLastLocation();
                writeLocationToFile(mCurrentLocation);
            }

            else if (action.equals(SensorService.ACTION_SCHEDULE_SURVEY)) {
                Log.d(TAG, "Received alarm event - schedule survey");
                int StartHour = intent.getIntExtra(START_HOUR, 0);
                int EndHour = intent.getIntExtra(END_HOUR, 0);
                int StartMin = intent.getIntExtra(START_MIN, 0);
                int EndMin = intent.getIntExtra(END_MIN, 0);
                int Interval = (((EndHour - StartHour) * 60) + (EndMin - StartMin)) / 6;
                int delay = Interval / 2;
                int Increment = Interval + delay;
                int TriggerInterval = Interval - delay;
                Log.d(TAG, String.valueOf(Interval));

                Date dt1 = new Date();
                dt1.setHours(StartHour);
                dt1.setMinutes(StartMin + delay);
                Date dt2 = new Date();
                dt2.setHours(StartHour);
                dt2.setMinutes(StartMin + Increment);
                Date dt3 = new Date();
                dt3.setHours(StartHour);
                dt3.setMinutes(StartMin + Increment + Interval);
                Date dt4 = new Date();
                dt4.setHours(StartHour);
                dt4.setMinutes(StartMin + Increment + (Interval * 2));
                Date dt5 = new Date();
                dt5.setHours(StartHour);
                dt5.setMinutes(StartMin + Increment + (Interval * 3));
                Date dt6 = new Date();
                dt6.setHours(StartHour);
                dt6.setMinutes(StartMin + Increment + (Interval * 4));
                rTask1 = new ScheduleSurvey(TriggerInterval);
                rTask2 = new ScheduleSurvey(TriggerInterval);
                rTask3 = new ScheduleSurvey(TriggerInterval);
                rTask4 = new ScheduleSurvey(TriggerInterval);
                rTask5 = new ScheduleSurvey(TriggerInterval);
                rTask6 = new ScheduleSurvey(TriggerInterval);
                t1.schedule(rTask1, dt1);
                t2.schedule(rTask2, dt2);
                t3.schedule(rTask3, dt3);
                t4.schedule(rTask4, dt4);
                t5.schedule(rTask5, dt5);
                t6.schedule(rTask6, dt6);
                setStatus(true);
            }
            //ADD THE PROCESSING AFTER THE RECEIVER RECEIVE THE FOLLOWUP MSG
            else if (action.equals(SensorService.ACTION_DRINK_FOLLOWUP)) {
                Log.d(TAG, "Received alarm event - schedule survey");
                //If timers already exists, cancel the current schedule tasks.
                //PurgeDrinkTimers();
                //trigger time is 30min 
                //long dIncrement = 30*60*1000;
                //test            
                if (dFlag == true) {
                    drinkSurveyTask.cancel();
                    dFlag = false;
                    dCount = 1;
                }
                long dIncrement = 30 * 60 * 1000;
                Date dt7 = new Date();
                dt7.setMinutes(dt7.getMinutes() + 30);
                drinkSurveyTask = new DrinkSurvey();
                t7.schedule(drinkSurveyTask, dt7, dIncrement);
                dFlag = true;
            }

            else if (action.equals(LocationControl.INTENT_ACTION_LOCATION)) {
                Log.d(TAG, "Received alarm event - location found");
                Location foundLocation = intent.getParcelableExtra(LocationControl.LOCATION_INTENT_KEY);

                if (foundLocation != null) {
                    HashMap<String, String> locationMap = new HashMap<String, String>();

                    locationMap.put("accuracy", foundLocation.getAccuracy() + "");

                    locationMap.put("longi", foundLocation.getLongitude() + "");

                    locationMap.put("lat", foundLocation.getLatitude() + "");

                    locationMap.put("source", foundLocation.getProvider());

                    writeLocationToFile(foundLocation);
                    ActivityRecognitionService.IsRetrievingUpdates = false;

                }
            } else if (action.equals(XMLSurveyActivity.INTENT_ACTION_SURVEY_RESULTS)) {
                Log.d(TAG, "Got survey results");
                Calendar cal = Calendar.getInstance();

                cal.setTimeInMillis(System.currentTimeMillis());

                @SuppressWarnings("unchecked")
                HashMap<String, List<String>> results = (HashMap<String, List<String>>) intent
                        .getSerializableExtra(XMLSurveyActivity.INTENT_EXTRA_SURVEY_RESULTS);
                String surveyName = intent.getStringExtra(XMLSurveyActivity.INTENT_EXTRA_SURVEY_NAME);

                try {
                    writeSurveyToFile(surveyName, results,
                            intent.getLongExtra(XMLSurveyActivity.INTENT_EXTRA_COMPLETION_TIME, 0L));
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "ERROR: Failed to write survey to file!");
                }
                Log.d(TAG, "Done writing file");

            }
        }
    };

    public static void CancelTask(TimerTask tTask) {
        if (tTask != null)
            tTask.cancel();
    }

    public static void CancelTimers(Timer t) {
        //if(t1!=null&&t2!=null&&t3!=null&&t4!=null&&t5!=null&&t6!=null&&mTimer!=null)
        if (t != null) {
            t.cancel();
            t.purge();
            //mTimer.cancel();
        }
    }

    public static void PurgeTimers(Timer t) {
        //if(t1!=null&&t2!=null&&t3!=null&&t4!=null&&t5!=null&&t6!=null&&mTimer!=null)
        if (t != null) {
            t.purge();
            //mTimer.cancel();
        }
    }

    public static void setStatus(boolean value) {
        IsScheduled = value;
    }

    public static boolean getStatus() {
        return IsScheduled;
    }

    protected void writeLocationToFile(Location l) {

        String toWrite;
        Calendar cl = Calendar.getInstance();
        SimpleDateFormat curFormater = new SimpleDateFormat("MMMMM_dd");
        String dateObj = curFormater.format(cl.getTime());
        File f = new File(BASE_PATH, "locations." + bluetoothMacAddress + "." + dateObj + ".txt");

        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone("US/Central"));
        toWrite = String.valueOf(cal.getTime()) + "," + l.getLatitude() + "," + l.getLongitude() + ","
                + l.getAccuracy() + "," + l.getProvider() + "," + getNameFromType(currentUserActivity);
        if (f != null) {
            try {
                writeToFile(f, toWrite);
                //sendDatatoServer("locations."+bluetoothMacAddress+"."+dateObj,toWrite);
                //Ricky
                TransmitData transmitData = new TransmitData();
                transmitData.execute("locations." + bluetoothMacAddress + "." + dateObj, toWrite);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private String getNameFromType(int activityType) {
        switch (activityType) {
        case DetectedActivity.IN_VEHICLE:
            return "in_vehicle";
        case DetectedActivity.ON_BICYCLE:
            return "on_bicycle";
        case DetectedActivity.ON_FOOT:
            return "on_foot";
        case DetectedActivity.STILL:
            return "still";
        case DetectedActivity.UNKNOWN:
            return "unknown";
        case DetectedActivity.TILTING:
            return "tilting";

        }
        return "unknown";
    }

    protected void writeSurveyToFile(String surveyName, HashMap<String, List<String>> surveyData, long time)
            throws IOException {
        Calendar cl = Calendar.getInstance();
        SimpleDateFormat curFormater = new SimpleDateFormat("MMMMM_dd");
        String dateObj = curFormater.format(cl.getTime());
        File f = new File(BASE_PATH, surveyName + "." + bluetoothMacAddress + "." + dateObj + ".txt");
        Log.d(TAG, "File: " + f.getName());

        StringBuilder sb = new StringBuilder(100);

        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(time);

        List<String> sorted = new ArrayList<String>(surveyData.keySet());
        Collections.sort(sorted);
        sb.append(c.getTime().toString());

        sb.append(",");

        for (int i = 0; i < sorted.size(); i++) {
            String key = sorted.get(i);
            List<String> data = surveyData.get(key);
            sb.append(key + ":");
            if (data == null)
                sb.append("-1");
            else {
                for (int j = 0; j < data.size(); j++) {
                    sb.append(data.get(j));
                    if (i != data.size() - 1)
                        sb.append("");
                }
            }
            if (i != sorted.size() - 1)
                sb.append(",");
        }
        sb.append("\n");
        //sendDatatoServer(surveyName+"."+bluetoothMacAddress+"."+dateObj,sb.toString());
        //Ricky 2013/12/09
        TransmitData transmitData = new TransmitData();
        transmitData.execute(surveyName + "." + bluetoothMacAddress + "." + dateObj, sb.toString());
        writeToFile(f, sb.toString());
        writeToFile(f, sb.toString());
    }

    protected void writeToFile(File f, String toWrite) throws IOException {
        FileWriter fw = new FileWriter(f, true);
        fw.write(toWrite + '\n');
        fw.flush();
        fw.close();
    }

    //------------------------------------------Chest Sensor Code Starts From Here ------------------------------------------------------

    BroadcastReceiver chestSensorReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(SensorService.ACTION_CONNECT_CHEST)) {
                Toast.makeText(getApplicationContext(), "Intent Received", Toast.LENGTH_LONG).show();
                String address = intent.getStringExtra(KEY_ADDRESS);
                String deviceName = intent.getStringExtra("KEY_DEVICE_NAME");
                equivitalThread = new EquivitalRunnable(address, deviceName, bluetoothMacAddress);
                equivitalThread.run();
                Calendar c = Calendar.getInstance();
                SimpleDateFormat curFormater = new SimpleDateFormat("MMMMM_dd");
                String dateObj = curFormater.format(c.getTime());
                String file_name = "Mac_Address" + dateObj + ".txt";
                File f = new File(BASE_PATH, file_name);

                if (f != null) {
                    try {
                        writeToFile(f, address);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }

                //connectToDevice(address);
            }
        }

    };

    //---------------------------------------Code to upload data to the server----------------------------------------------//
    //Ricky 2013/12/09
    //Use AsyncTask to deal with not responding things
    private class TransmitData extends AsyncTask<String, Void, Boolean> {

        @Override
        protected Boolean doInBackground(String... strings) {
            // TODO Auto-generated method stub
            String fileName = strings[0];
            String dataToSend = strings[1];
            if (checkDataConnectivity()) {
                HttpPost request = new HttpPost(
                        "http://dslsrv8.cs.missouri.edu/~rs79c/Server/Crt/writeArrayToFile.php");
                //HttpPost request = new HttpPost("http://dslsrv8.cs.missouri.edu/~rs79c/Server/Test/writeArrayToFile.php");
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                //file_name 
                params.add(new BasicNameValuePair("file_name", fileName));
                //data                       
                params.add(new BasicNameValuePair("data", dataToSend));
                try {

                    request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
                    HttpResponse response = new DefaultHttpClient().execute(request);
                    if (response.getStatusLine().getStatusCode() == 200) {
                        String result = EntityUtils.toString(response.getEntity());
                        Log.d("Sensor Data Point Info", result);
                        // Log.d("Wrist Sensor Data Point Info","Data Point Successfully Uploaded!");
                    }
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            }

            else {
                Log.d("Sensor Data Point Info", "No Network Connection:Data Point was not uploaded");
                Toast.makeText(serviceContext, errMSG, Toast.LENGTH_LONG).show();
                return false;
            }

        }

    }
    /*   
    public static void sendDatatoServer(String FileName,String DataToSend)
    {
       if (checkDataConnectivity())
        {
        
       //HttpPost request = new HttpPost("http://dslsrv8.cs.missouri.edu/~rs79c/Server/Crt/writeArrayToFile.php");
       //new test URL   
       HttpPost request = new HttpPost("http://dslsrv8.cs.missouri.edu/~rs79c/Server/Test/writeArrayToFile.php");
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    //file_name 
    params.add(new BasicNameValuePair("file_name",FileName));
    //data
    //Modified to deal with the additional line for location data
    //Ricky 2013/11/21
    //params.add(new BasicNameValuePair("data",DataToSend+"\n"));
    params.add(new BasicNameValuePair("data",DataToSend));
        
        
    try {
        request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
        HttpResponse response = new DefaultHttpClient().execute(request);
        if(response.getStatusLine().getStatusCode() == 200){
            String result = EntityUtils.toString(response.getEntity());
            //Toast.makeText(serviceContext,"Data Point Successfully Uploaded", Toast.LENGTH_LONG).show();
        }
    } catch (Exception e) {
            
       Toast.makeText(serviceContext,"Error during HTTP POST REQUEST",Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }
        }
        else Toast.makeText(serviceContext, errMSG, Toast.LENGTH_LONG).show();
     }
    */

    public static boolean checkDataConnectivity() {
        ConnectivityManager connectivity = (ConnectivityManager) serviceContext
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null) {
                for (int i = 0; i < info.length; i++) {
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "Connection Failed", Toast.LENGTH_SHORT).show();
    }

    /*
      * Called by Location Services when the request to connect the
      * client finishes successfully. At this point, you can
      * request the current location or start periodic updates
      */
    @Override
    public void onConnected(Bundle dataBundle) {
        // Display the connection status
        Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
    }

    /*
     * Called by Location Services if the connection to the
     * location client drops because of an error.
     */
    @Override
    public void onDisconnected() {
        // Display the connection status
        Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
    }
}