com.aware.plugin.polarhrm.Plugin.java Source code

Java tutorial

Introduction

Here is the source code for com.aware.plugin.polarhrm.Plugin.java

Source

package com.aware.plugin.polarhrm;

import java.util.Timer;
import java.util.TimerTask;

import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.util.SparseArray;

import com.aware.Aware;
import com.aware.Aware_Preferences;
import com.aware.plugin.polarhrm.PolarHRM_Provider.PolarHRM_Data;
import com.aware.plugin.polarhrm.PolarHRM_Provider.PolarHRM_Profile;
import com.aware.utils.Aware_Plugin;
import com.aware.utils.Text_2_speech;
import com.google.android.apps.mytracks.services.sensors.SensorManager;
import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory;

/**
 * This plugin connects to a Polar HRM<br/>
 * We use Google's MyTracks code to parse Polar's HRM as it is not freely available without a license.<br/>
 * 
 * @author Denzil Ferreira <denzil.ferreira@ee.oulu.fi>
 *
 */
public class Plugin extends Aware_Plugin {

    private static final BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();

    private static SensorManager polarHRM = null;
    private static Timer updater = null;
    private final UpdateHR updateHR = new UpdateHR();

    private static final int NOTIFICATION_ID = 123;

    private static NotificationManager notManager = null;
    private static NotificationCompat.Builder notificationBuilder = null;

    private static SharedPreferences prefs = null;

    private static final int REFRESH = 1;

    private static int last_zone = -1;
    private static int last_heart_rate = 0;

    private static Algorithm algorithm = null;

    public static final String ACTION_AWARE_POLAR_HEARTRATE = "ACTION_AWARE_POLAR_HEARTRATE";

    private Handler uiHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == REFRESH) {
                CONTEXT_PRODUCER.onContext();
                showUI();
                return true;
            }
            return false;
        }
    });

    public static class BluetoothState extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equalsIgnoreCase(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                int connectionState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
                if (connectionState == BluetoothAdapter.STATE_ON) {
                    if (polarHRM == null)
                        polarHRM = SensorManagerFactory.getSystemSensorManager(context);
                } else if (connectionState == BluetoothAdapter.STATE_OFF) {
                    if (polarHRM != null)
                        polarHRM.stopSensor();
                }
            }
        }
    }

    private static final BluetoothState btStateListener = new BluetoothState();

    private class UpdateHR extends TimerTask {
        @Override
        public void run() {
            if (polarHRM != null && polarHRM.isEnabled() && polarHRM.isSensorDataSetValid()) {
                last_heart_rate = polarHRM.getSensorDataSet().getHeartRate().getValue();

                ContentValues rowData = new ContentValues();
                rowData.put(PolarHRM_Data.TIMESTAMP, System.currentTimeMillis());
                rowData.put(PolarHRM_Data.DEVICE_ID,
                        Aware.getSetting(getContentResolver(), Aware_Preferences.DEVICE_ID));
                rowData.put(PolarHRM_Data.HEART_RATE, last_heart_rate);
                rowData.put(PolarHRM_Data.HEART_RATE_ZONE, algorithm.getZone(last_heart_rate));
                getContentResolver().insert(PolarHRM_Data.CONTENT_URI, rowData);

                uiHandler.sendEmptyMessage(REFRESH);
            }
        }
    }

    private void showUI() {
        if (algorithm == null)
            return;

        notificationBuilder.setContentText(
                "Heart rate: " + ((last_heart_rate > 0) ? last_heart_rate : "waiting for connection"));
        notificationBuilder.setContentTitle("Heart rate monitor");

        SparseArray<double[]> zones = algorithm.getZones();
        int zone = algorithm.getZone(last_heart_rate);
        double[] range = zones.get(zone);
        String announce = "";
        switch (zone) {
        case Algorithm.HR_ZONE_RECOVERY:
            notificationBuilder.setSubText("HR zone: recovery [" + range[0] + ";" + range[1] + "]");
            announce = "Recovery";
            break;
        case Algorithm.HR_ZONE_AEROBIC:
            notificationBuilder.setSubText("HR zone: aerobic [" + range[0] + ";" + range[1] + "]");
            announce = "Medium";
            break;
        case Algorithm.HR_ZONE_ANAEROBIC:
            notificationBuilder.setSubText("HR zone: anaerobic [" + range[0] + ";" + range[1] + "]");
            announce = "High";
            break;
        case Algorithm.HR_ZONE_RED_LINE:
            notificationBuilder.setSubText("HR zone: red line [" + range[0] + ";" + range[1] + "]");
            announce = "Extreme";
            break;
        case Algorithm.HR_ZONE_REGULAR:
            notificationBuilder
                    .setSubText("HR zone: regular, less than " + zones.get(Algorithm.HR_ZONE_RECOVERY)[0]);
            announce = "Relaxed";
            break;
        }

        if (zone != last_zone && prefs.getBoolean("notify", false) && last_zone != -1) {
            Intent tts = new Intent(getApplicationContext(), Text_2_speech.class);
            tts.putExtra(Text_2_speech.EXTRA_TTS_TEXT, announce);
            startService(tts);
        }
        last_zone = zone;

        notificationBuilder.setSmallIcon(R.drawable.ic_stat_polar_hrm);
        notificationBuilder.setContentIntent(null);
        notificationBuilder.setOngoing(true);
        notificationBuilder.setAutoCancel(true);
        notificationBuilder.setWhen(System.currentTimeMillis());
        notManager.notify(NOTIFICATION_ID, notificationBuilder.build());
    }

    @Override
    public void onCreate() {
        super.onCreate();
        TAG = "PolarHRM";

        CONTEXT_PRODUCER = new Aware_Plugin.ContextProducer() {
            @Override
            public void onContext() {
                Intent heartRate = new Intent(ACTION_AWARE_POLAR_HEARTRATE);
                sendBroadcast(heartRate);
            }
        };

        DATABASE_TABLES = PolarHRM_Provider.DATABASE_TABLES;
        TABLES_FIELDS = PolarHRM_Provider.TABLES_FIELDS;
        CONTEXT_URIS = new Uri[] { PolarHRM_Data.CONTENT_URI, PolarHRM_Profile.CONTENT_URI };

        notManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationBuilder = new NotificationCompat.Builder(this);

        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(btStateListener, filter);

        prefs = getSharedPreferences(getPackageName(), MODE_MULTI_PROCESS);

        if (btAdapter != null && !btAdapter.isEnabled()) {
            Intent makeEnabled = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            makeEnabled.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
            startActivity(makeEnabled);
        }

        updater = new Timer();
        updater.scheduleAtFixedRate(updateHR, 0, 2000);

        if (!prefs.contains("age")) {
            Intent hrm_params = new Intent(getApplicationContext(), Settings.class);
            hrm_params.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(hrm_params);
        } else {
            algorithm = new Algorithm(prefs.getInt("age", 25), prefs.getInt("rhr", 70));
            SparseArray<double[]> hr_zones = algorithm.getZones();

            ContentValues rowData = new ContentValues();
            rowData.put(PolarHRM_Profile.TIMESTAMP, System.currentTimeMillis());
            rowData.put(PolarHRM_Profile.DEVICE_ID,
                    Aware.getSetting(getContentResolver(), Aware_Preferences.DEVICE_ID));
            rowData.put(PolarHRM_Profile.AGE, prefs.getInt("age", 25));
            rowData.put(PolarHRM_Profile.RESTING_HR, prefs.getInt("rhr", 70));
            rowData.put(PolarHRM_Profile.RECOVERY_MIN, hr_zones.get(0)[0]);
            rowData.put(PolarHRM_Profile.RECOVERY_MAX, hr_zones.get(0)[1]);
            rowData.put(PolarHRM_Profile.AEROBIC_MIN, hr_zones.get(1)[0]);
            rowData.put(PolarHRM_Profile.AEROBIC_MAX, hr_zones.get(1)[1]);
            rowData.put(PolarHRM_Profile.ANAEROBIC_MIN, hr_zones.get(2)[0]);
            rowData.put(PolarHRM_Profile.ANAEROBIC_MAX, hr_zones.get(2)[1]);
            rowData.put(PolarHRM_Profile.RED_LINE_MIN, hr_zones.get(3)[0]);
            rowData.put(PolarHRM_Profile.RED_LINE_MAX, hr_zones.get(3)[1]);

            getContentResolver().insert(PolarHRM_Profile.CONTENT_URI, rowData);
        }

        showUI();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (btAdapter.isEnabled()) {
            if (polarHRM == null)
                polarHRM = SensorManagerFactory.getSystemSensorManager(this);
            if (algorithm == null)
                algorithm = new Algorithm(prefs.getInt("age", 25), prefs.getInt("rhr", 70));
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //terminate text-to-speech service
        Intent tts = new Intent(getApplicationContext(), Text_2_speech.class);
        stopService(tts);
        //Don't update UI anymore
        updater.cancel();
        //Stop checking the bluetooth state
        unregisterReceiver(btStateListener);
        //Stop listening to the Polar HRM
        polarHRM.stopSensor();
        //Remove notification
        notManager.cancel(NOTIFICATION_ID);
    }
}