Java tutorial
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); } }