package com.solderbyte.openfit; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Set; import com.android.vending.billing.IInAppBillingService; import com.solderbyte.openfit.ui.OpenFitActivity; import com.solderbyte.openfit.util.OpenFitData; import com.solderbyte.openfit.util.OpenFitIntent; import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.provider.ContactsContract.PhoneLookup; import android.support.v4.app.NotificationCompat; import android.telephony.PhoneStateListener; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.media.ToneGenerator; import android.media.AudioManager; import android.util.Log; import android.widget.Toast; @SuppressLint("HandlerLeak") public class OpenFitService extends Service { private static final String LOG_TAG = "OpenFit:OpenFitService"; private OpenFitSavedPreferences oPrefs; private ApplicationManager appManager; private BluetoothLeService bluetoothLeService; private GoogleFit gFit = null; private Billing billing = null; private IInAppBillingService billingService; private Handler mHandler; private PackageManager pManager; private static ReconnectBluetoothThread reconnectThread; private static FindSoundThread findSoundThread; private int notificationId = 28518; private boolean smsEnabled = false; private boolean phoneEnabled = false; private boolean weatherClockEnabled = false; private boolean weatherNotificationEnabled = false; private boolean weatherClockReq = false; private boolean googleFitEnabled = false; private boolean googleFitSyncing = false; private boolean isReconnect = false; private boolean reconnecting = false; private boolean isStopping = false; private boolean isFinding = false; private boolean isPremium = false; private boolean isGpsAllowed = false; private boolean locationForWeather = true; private boolean locationForExercise = false; private boolean locationForExerciseSubscribe = false; private boolean checkGPSReady = false; private int currentExerciseID = -1; private int currentExerciseType = -1; private SmsListener smsListener; private MmsListener mmsListener; private TelephonyManager telephony; private DialerListener dailerListener; private Notification notification; private static ExerciseGPSStorage gpsData = null; private String lastPhoneNumber = ""; @Override public IBinder onBind(Intent intent) { Log.d(LOG_TAG, "onBind"); return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(LOG_TAG, "OpenFit Service onStartCommand: " + flags); // register receivers this.registerReceiver(serviceStopReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_STOP)); this.registerReceiver(btReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_BT)); this.registerReceiver(notificationReceiver, new IntentFilter(OpenFitIntent.INTENT_NOTIFICATION)); this.registerReceiver(smsReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_SMS)); this.registerReceiver(mmsReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_MMS)); this.registerReceiver(phoneReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_PHONE)); this.registerReceiver(phoneIdleReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_PHONE_IDLE)); this.registerReceiver(phoneOffhookReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_PHONE_OFFHOOK)); this.registerReceiver(mediaReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_MEDIA)); this.registerReceiver(alarmReceiver, Alarm.getIntentFilter()); this.registerReceiver(weatherReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_WEATHER)); this.registerReceiver(locationReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_LOCATION)); this.registerReceiver(cronReceiver, new IntentFilter(OpenFitIntent.INTENT_SERVICE_CRONJOB)); this.registerReceiver(googleFitReceiver, new IntentFilter(OpenFitIntent.INTENT_GOOGLE_FIT)); this.registerReceiver(billingReceiver, new IntentFilter(OpenFitIntent.INTENT_BILLING)); this.registerReceiver(saveRejectMessagesReceiver, new IntentFilter(OpenFitIntent.INTENT_REJECTMESSAGES_SAVE)); // start modules pManager = this.getPackageManager(); MediaController.init(this); LocationInfo.init(this); Weather.init(this); Cronjob.init(this); startCronJob(); startBillingServices(); // start service this.createNotification(false); this.startBluetoothHandler(); this.startBluetoothService(); this.startNotificationListenerService(); this.startGoogleApiClient(); this.startForeground(notificationId, notification); // load saved preferences oPrefs = new OpenFitSavedPreferences(this); appManager = new ApplicationManager(); gpsData = new ExerciseGPSStorage(this); this.sendNotificationApplications(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.d(LOG_TAG, "onDestroy"); unregisterReceiver(serviceStopReceiver); LocationInfo.removeUpdates(); super.onDestroy(); } protected ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { Log.d(LOG_TAG, "Bluetooth service connected"); bluetoothLeService = ((BluetoothLeService.LocalBinder)service).getService(); if(!bluetoothLeService.initialize()) { Log.e(LOG_TAG, "Unable to initialize BluetoothLE"); } bluetoothLeService.setHandler(mHandler); sendServiceStarted(); sendUIPreferences(); // auto connect bluetoothLeService.connectRfcomm(); isReconnect = true; } @Override public void onServiceDisconnected(ComponentName componentName) { Log.d(LOG_TAG, "Bluetooth onServiceDisconnected"); bluetoothLeService = null; } }; public void sendUIPreferences() { // update ui if(BluetoothLeService.isEnabled) { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_IS_ENABLED); sendBroadcast(i); } else { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_IS_ENABLED_FAILED); sendBroadcast(i); } if(BluetoothLeService.isConnected) { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_IS_CONNECTED); sendBroadcast(i); createNotification(true); } else { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_IS_DISCONNCTED); sendBroadcast(i); createNotification(false); } if(oPrefs.preference_list_devices_value != OpenFitIntent.DEFAULT) { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_DEVICE_NAME); i.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, oPrefs.getString("preference_list_devices_entry")); sendBroadcast(i); bluetoothLeService.setEntries(); bluetoothLeService.setDevice(oPrefs.preference_list_devices_value); Log.d(LOG_TAG, "Service restored device: " + oPrefs.getString("preference_list_weather_entry") + ":" + oPrefs.getString("preference_list_weather_value")); } if(oPrefs.preference_list_weather_value != OpenFitIntent.DEFAULT) { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_WEATHER); i.putExtra(OpenFitIntent.EXTRA_WEATHER_ENTRY, oPrefs.getString("preference_list_weather_entry")); i.putExtra(OpenFitIntent.EXTRA_WEATHER_VALUE, oPrefs.getString("preference_list_weather_value")); sendBroadcast(i); startWeather(oPrefs.getString("preference_list_weather_value")); } Intent s = new Intent(OpenFitIntent.INTENT_UI_BT); s.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_SMS); s.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, oPrefs.getBoolean("preference_checkbox_sms")); sendBroadcast(s); startSmsListener(oPrefs.getBoolean("preference_checkbox_sms")); Intent g = new Intent(OpenFitIntent.INTENT_UI_BT); g.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_GPS); g.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, oPrefs.getBoolean("preference_checkbox_exercise_gps")); sendBroadcast(g); isGpsAllowed = oPrefs.getBoolean("preference_checkbox_exercise_gps"); Intent p = new Intent(OpenFitIntent.INTENT_UI_BT); p.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_PHONE); p.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, oPrefs.getBoolean("preference_checkbox_phone")); sendBroadcast(p); startDailerListener(oPrefs.getBoolean("preference_checkbox_phone")); Intent t = new Intent(OpenFitIntent.INTENT_UI_BT); t.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_TIME); t.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, oPrefs.getBoolean("preference_checkbox_time")); sendBroadcast(t); } public void sendNotificationApplications() { ArrayList<String> listeningListAppNames = new ArrayList<String>(); ArrayList<String> listeningListPackageNames = new ArrayList<String>(); Set<String> setPackageNames = oPrefs.getSet(); for(String packageName : setPackageNames) { listeningListAppNames.add(oPrefs.getString(packageName)); listeningListPackageNames.add(packageName); Log.d(LOG_TAG, "Listening Package: " + packageName); appManager.addNotificationApp(packageName); } Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_APPLICATIONS); i.putStringArrayListExtra(OpenFitIntent.EXTRA_APPLICATIONS_PACKAGE_NAME, listeningListPackageNames); i.putStringArrayListExtra(OpenFitIntent.EXTRA_APPLICATIONS_APP_NAME, listeningListAppNames); sendBroadcast(i); Intent a = new Intent(OpenFitIntent.INTENT_SERVICE_NOTIFICATION_APPLICATIONS); a.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.INTENT_SERVICE_NOTIFICATION_APPLICATIONS); a.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, appManager.getNotificationApplications()); sendBroadcast(a); } public void sendServiceStarted() { Log.d(LOG_TAG, "sendServiceStarted"); Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.INTENT_SERVICE_START); sendBroadcast(i); } public void startBluetoothService() { Log.d(LOG_TAG, "Starting bluetooth service"); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); this.bindService(gattServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE); } public void reconnectBluetoothService() { Log.d(LOG_TAG, "starting reconnect thread"); if(isReconnect) { reconnectThread = new ReconnectBluetoothThread(); reconnectThread.start(); reconnecting = true; } } public void reconnectBluetoothStop() { Log.d(LOG_TAG, "stopping reconnect thread"); reconnecting = false; if(reconnectThread != null) { reconnectThread.close(); reconnectThread = null; Log.d(LOG_TAG, "stopped reconnect thread"); } } public void startBluetoothHandler() { // setup message handler Log.d(LOG_TAG, "Starting up bluetooth handler"); mHandler = new Handler() { @Override public void handleMessage(Message msg) { Log.d(LOG_TAG, "handleMessage: "+msg.getData()); String bluetoothMessage = msg.getData().getString(OpenFitIntent.EXTRA_BLUETOOTH); String bluetoothDevice = msg.getData().getString(OpenFitIntent.EXTRA_BLUETOOTH_DEVICE); String bluetoothDevicesList = msg.getData().getString(OpenFitIntent.EXTRA_BLUETOOTH_DEVICE_LIST); String bluetoothData = msg.getData().getString(OpenFitIntent.EXTRA_BLUETOOTH_DATA); if(bluetoothMessage != null && !bluetoothMessage.isEmpty()) { Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, bluetoothMessage); sendBroadcast(i); } if(bluetoothDevice != null && !bluetoothDevice.isEmpty()) { String[] sDevice = bluetoothDevice.split(","); String sDeviceName = sDevice[0]; String sDeviceAddress = sDevice[1]; Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, bluetoothDevice); i.putExtra(OpenFitIntent.EXTRA_DEVICE_NAME, sDeviceName); i.putExtra(OpenFitIntent.EXTRA_DEVICE_ADDRESS, sDeviceAddress); sendBroadcast(i); } if(bluetoothDevicesList != null && !bluetoothDevicesList.isEmpty()) { CharSequence[] bluetoothEntries = msg.getData().getCharSequenceArray(OpenFitIntent.EXTRA_BLUETOOTH_ENTRIES); CharSequence[] bluetoothEntryValues = msg.getData().getCharSequenceArray(OpenFitIntent.EXTRA_BLUETOOTH_ENTRIES_VALUES); Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, bluetoothDevicesList); i.putExtra(OpenFitIntent.EXTRA_BLUETOOTH_ENTRIES, bluetoothEntries); i.putExtra(OpenFitIntent.EXTRA_BLUETOOTH_ENTRIES_VALUES, bluetoothEntryValues); sendBroadcast(i); } if(bluetoothData != null && !bluetoothData.isEmpty()) { byte[] byteArray = msg.getData().getByteArray(OpenFitIntent.INTENT_EXTRA_DATA); handleBluetoothData(byteArray); } if(bluetoothMessage != null && bluetoothMessage.equals(OpenFitIntent.EXTRA_IS_CONNECTED_RFCOMM)) { if(reconnecting) { reconnectBluetoothStop(); } if(!isStopping) { createNotification(true); } } if(bluetoothMessage != null && bluetoothMessage.equals(OpenFitIntent.EXTRA_IS_DISCONNECTED_RFCOMM)) { locationForExercise = locationForWeather = false; LocationInfo.removeUpdates(); if(isReconnect) { reconnectBluetoothService(); } if(!isStopping) { createNotification(false); } } } }; } public void handleUIMessage(String message, Intent intent) { if(message != null && !message.isEmpty() && bluetoothLeService != null) { if(message.equals(OpenFitIntent.ACTION_ENABLE)) { bluetoothLeService.enableBluetooth(); } if(message.equals(OpenFitIntent.ACTION_DISABLE)) { bluetoothLeService.disableBluetooth(); } if(message.equals(OpenFitIntent.ACTION_SCAN)) { bluetoothLeService.scanLeDevice(); } if(message.equals(OpenFitIntent.ACTION_CONNECT)) { bluetoothLeService.connectRfcomm(); isReconnect = true; } if(message.equals(OpenFitIntent.ACTION_DISCONNECT)) { bluetoothLeService.disconnectRfcomm(); isReconnect = false; } if(message.equals(OpenFitIntent.ACTION_SET_ENTRIES)) { bluetoothLeService.setEntries(); } if(message.equals(OpenFitIntent.ACTION_SET_DEVICE)) { String deviceMac = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_DATA); bluetoothLeService.setDevice(deviceMac); } if(message.equals(OpenFitIntent.ACTION_TIME)) { String s = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_DATA); boolean value = Boolean.parseBoolean(s); sendTime(value); } if(message.equals(OpenFitIntent.ACTION_WEATHER)) { String weatherValue = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_DATA); startWeather(weatherValue); } if(message.equals(OpenFitIntent.ACTION_FITNESS)) { sendFitnessRequest(); } if(message.equals(OpenFitIntent.ACTION_PHONE)) { String data = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_DATA); boolean enabled = Boolean.parseBoolean(data); startDailerListener(enabled); } if(message.equals(OpenFitIntent.ACTION_SMS)) { String data = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_DATA); Boolean enabled = Boolean.parseBoolean(data); startSmsListener(enabled); } if(message.equals(OpenFitIntent.ACTION_GPS)) { String data = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_DATA); Boolean enabled = Boolean.parseBoolean(data); isGpsAllowed = enabled; if(!isGpsAllowed && !locationForWeather) { currentExerciseID = -1; LocationInfo.removeUpdates(); } } if(message.equals(OpenFitIntent.ACTION_UI_STATUS)) { sendUIPreferences(); } } } public void handleBluetoothData(byte[] data) { Log.d(LOG_TAG, "Service received: " + OpenFitApi.byteArrayToHexString(data)); if(Arrays.equals(data, OpenFitApi.getReady())) { Log.d(LOG_TAG, "Recieved ready message"); sendBluetoothBytes(OpenFitApi.getUpdate()); sendBluetoothBytes(OpenFitApi.getUpdateFollowUp()); sendBluetoothBytes(OpenFitApi.getFotaCommand()); sendTime(oPrefs.getBoolean("preference_checkbox_time")); // send reject messages to wingtip saveRejectMessagesToBracelet(); } if(Arrays.equals(data, OpenFitApi.getFindStart())) { sendFindStart(); } if(Arrays.equals(data, OpenFitApi.getFindStop())) { sendFindStop(); } if(Arrays.equals(data, OpenFitApi.getMediaPrev())) { sendMediaPrev(); } if(Arrays.equals(data, OpenFitApi.getMediaNext())) { sendMediaNext(); } if(Arrays.equals(data, OpenFitApi.getMediaPlay())) { sendMediaPlay(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getMediaVolume()))) { byte vol = data[data.length - 1]; sendMediaVolume(vol, false); } if(Arrays.equals(data, OpenFitApi.getMediaReqStart())) { sendMediaRes(); } if(Arrays.equals(data, OpenFitApi.getOpenAlarmCleared())) { //DismissAlarm(); } if(Arrays.equals(data, OpenFitApi.getOpenAlarmSnoozed())) { //snoozeAlarm(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getOpenRejectCall()))) { endCall(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getOpenRejectCallMessage()))) { sendRejectMessage(OpenFitApi.byteArrayToHexString(data).replace(OpenFitApi.byteArrayToHexString(OpenFitApi.getOpenRejectCallMessage()), ""), lastPhoneNumber); } if(Arrays.equals(data, OpenFitApi.getOpenWeatherReq())) { Log.d(LOG_TAG, "Requesting weather"); weatherClockReq = true; getWeather(); } if(Arrays.equals(data, OpenFitApi.getFitnessMenu())) { sendFitnessMenuResponse(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getFitnessCycling()))) { sendFitnessCycling(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getFitnessRunning()))) { sendFitnessRunning(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.CYCLING))) || OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.HIKING))) || OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.WALK))) || OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.RUN)))) { Log.d(LOG_TAG, "Exercise is starting"); currentExerciseID = -1; if(isGpsAllowed) { checkGPSReady = true; locationForExercise = true; if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.CYCLING)))) { currentExerciseType = OpenFitData.CYCLING_EXERCISE; } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.HIKING)))) { currentExerciseType = OpenFitData.HIKING_EXERCISE; } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.WALK)))) { currentExerciseType = OpenFitData.WALK_EXERCISE; } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSReady(OpenFitData.RUN)))) { currentExerciseType = OpenFitData.RUN_EXERCISE; } LocationInfo.resetData(); LocationInfo.removeUpdates(); LocationInfo.listenForLocation(false); } } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSSubscribe()))) { Log.d(LOG_TAG, "Subscribe GPS"); sendCurrentGPSData(); locationForExerciseSubscribe = true; //LocationInfo.listenForLocation(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSUnSubscribe()))) { Log.d(LOG_TAG, "Unsubscribe GPS"); locationForExerciseSubscribe = false; } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getSync()))) { Log.d(LOG_TAG, "SYNC REQUEST"); sendFitnessRequest(); } if(OpenFitApi.byteArrayToHexString(data).contains(OpenFitApi.byteArrayToHexString(OpenFitApi.getGPSEnd()))) { Log.d(LOG_TAG, "GPS END"); if(currentExerciseID > -1) { sendGPSResult(); } LocationInfo.resetData(); LocationInfo.removeUpdates(); locationForExercise = false; } if(Fitness.isPendingData()) { handleFitnessData(data); int eSize = Fitness.getExerciseDataList().size(); Log.d(LOG_TAG, "Current exercise id: " + currentExerciseID + ", exercise size: " + eSize); if(currentExerciseID > -1 && eSize > 0) { gpsData.updateExerciseTimestamp(currentExerciseID, Fitness.getExerciseDataList().get(eSize - 1).getTimeStamp(), Fitness.getExerciseDataList().get(eSize - 1).getTimeStampEnd()); // currentExerciseID = -1; } // update profile data if(Fitness.getProfileData() != null) { gpsData.updateProfile(Fitness.getProfileData().getHeight(), Fitness.getProfileData().getWeight()); } } if(OpenFitApi.byteArrayToHexString(data).startsWith(OpenFitApi.byteArrayToHexString(OpenFitApi.getFitness()))) { if(Fitness.isFitnessData(data)) { Log.d(LOG_TAG, "Fitness data found setting listener"); handleFitnessData(data); int eSize = Fitness.getExerciseDataList().size(); Log.d(LOG_TAG, "Current exercise id: " + currentExerciseID + ", exercise size: " + eSize); if(currentExerciseID > -1 && eSize > 0) { gpsData.updateExerciseTimestamp(currentExerciseID, Fitness.getExerciseDataList().get(eSize - 1).getTimeStamp(), Fitness.getExerciseDataList().get(eSize - 1).getTimeStampEnd()); // currentExerciseID = -1; } // update profile data if(Fitness.getProfileData() != null) { gpsData.updateProfile(Fitness.getProfileData().getHeight(), Fitness.getProfileData().getWeight()); } } else { Log.d(LOG_TAG, "Fitness data false"); } } } public void handleFitnessData(byte[] data) { Fitness.addData(data); if(!Fitness.isPendingData()) { Log.d(LOG_TAG, "Fitness data complete"); Fitness.parseData(); Intent i = new Intent(OpenFitIntent.INTENT_UI_BT); i.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.EXTRA_FITNESS); i.putExtra(OpenFitIntent.EXTRA_PEDOMETER_TOTAL, Fitness.getPedometerTotal()); i.putParcelableArrayListExtra(OpenFitIntent.EXTRA_PEDOMETER_LIST, Fitness.getPedometerList()); i.putParcelableArrayListExtra(OpenFitIntent.EXTRA_PEDOMETER_DAILY_LIST, Fitness.getPedometerDailyList()); i.putParcelableArrayListExtra(OpenFitIntent.EXTRA_SLEEP_INFO_LIST, Fitness.getSleepInfoList()); i.putParcelableArrayListExtra(OpenFitIntent.EXTRA_EXERCISE_LIST, Fitness.getExerciseDataList()); i.putParcelableArrayListExtra(OpenFitIntent.EXTRA_SLEEP_LIST, Fitness.getSleepList()); i.putParcelableArrayListExtra(OpenFitIntent.EXTRA_HEARTRATE_LIST, Fitness.getHeartRateList()); i.putExtra(OpenFitIntent.EXTRA_PROFILE_DATA, Fitness.getProfileData()); sendBroadcast(i); if(googleFitSyncing) { startFitnessSync(Fitness.getPedometerList(), Fitness.getExerciseDataList(), Fitness.getSleepList(), Fitness.getSleepInfoList(), Fitness.getHeartRateList(), Fitness.getProfileData()); } } } public void startNotificationListenerService() { Log.d(LOG_TAG, "Starting notification service"); Intent notificationIntent = new Intent(this, NotificationService.class); this.startService(notificationIntent); } public void startDailerListener(Boolean enabled) { phoneEnabled = enabled; Log.d(LOG_TAG, "Starting Phone Listeners"); if(phoneEnabled) { dailerListener = new DialerListener(this); telephony = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); telephony.listen(dailerListener, PhoneStateListener.LISTEN_CALL_STATE); Log.d(LOG_TAG, "phone listening"); } else { if(telephony != null) { telephony.listen(dailerListener, PhoneStateListener.LISTEN_NONE); dailerListener.destroy(); } } } public void startSmsListener(Boolean enabled) { smsEnabled = enabled; Log.d(LOG_TAG, "Starting SMS/MMS Listeners"); if(smsEnabled) { if(smsListener == null) { smsListener = new SmsListener(this); IntentFilter smsFilter = new IntentFilter(OpenFitIntent.INTENT_ANDROID_SMS); this.registerReceiver(smsListener, smsFilter); mmsListener = new MmsListener(this); IntentFilter mmsFilter = new IntentFilter(OpenFitIntent.INTENT_ANDROID_SMS); this.registerReceiver(mmsListener, mmsFilter); } } else { if(smsListener != null) { this.unregisterReceiver(smsListener); smsListener = null; this.unregisterReceiver(mmsListener); mmsListener = null; } } } public void createNotification(boolean connected) { Log.d(LOG_TAG, "Creating Notification: " + connected); Intent stopService = new Intent(OpenFitIntent.INTENT_SERVICE_STOP); Intent startActivity = new Intent(this, OpenFitActivity.class); PendingIntent startIntent = PendingIntent.getActivity(this, 0, startActivity, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent stopIntent = PendingIntent.getBroadcast(this, 0, stopService, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this); nBuilder.setSmallIcon(R.drawable.open_fit_notification); nBuilder.setContentTitle(getString(R.string.notification_title)); if(connected) { nBuilder.setContentText(getString(R.string.notification_connected)); } else { nBuilder.setContentText(getString(R.string.notification_disconnected)); } nBuilder.setContentIntent(startIntent); nBuilder.setAutoCancel(true); nBuilder.setOngoing(true); //nBuilder.setPriority(NotificationCompat.PRIORITY_MIN); nBuilder.addAction(R.drawable.open_off_noti, getString(R.string.notification_button_close), stopIntent); if(connected) { Intent cIntent = new Intent(OpenFitIntent.INTENT_SERVICE_BT); cIntent.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.ACTION_DISCONNECT); PendingIntent pConnect = PendingIntent.getBroadcast(this, 0, cIntent, PendingIntent.FLAG_UPDATE_CURRENT); nBuilder.addAction(R.drawable.open_btd, getString(R.string.notification_button_disconnect), pConnect); } else { Intent cIntent = new Intent(OpenFitIntent.INTENT_SERVICE_BT); cIntent.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.ACTION_CONNECT); PendingIntent pConnect = PendingIntent.getBroadcast(this, 0, cIntent, PendingIntent.FLAG_UPDATE_CURRENT); nBuilder.addAction(R.drawable.open_btc, getString(R.string.notification_button_connect), pConnect); } // Sets an ID for the notification NotificationManager nManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE); notification = nBuilder.build(); nManager.notify(notificationId, notification); } public void clearNotification() { NotificationManager nManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE); nManager.cancel(notificationId); } public void startBillingServices() { billing = new Billing(); billing.setContext(this); Intent billingServiceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND"); billingServiceIntent.setPackage("com.android.vending"); bindService(billingServiceIntent, billingServiceConnection, Context.BIND_AUTO_CREATE); } public ServiceConnection billingServiceConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.d(LOG_TAG, "Billing service disconnected"); billingService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(LOG_TAG, "Billing service connected"); billingService = IInAppBillingService.Stub.asInterface(service); billing.setService(billingService); billing.getSkuDetails(); billing.verifyPremium(); } }; public void sendBluetoothBytes(byte[] bytes) { if(bluetoothLeService != null) { bluetoothLeService.write(bytes); } else { Log.w(LOG_TAG, "bluetoothLeService is null"); } } public void startWeather(String weatherValue) { if(weatherValue.equals(OpenFitIntent.NONE)) { weatherNotificationEnabled = false; weatherClockEnabled = false; } else { String[] values = weatherValue.split(","); if(values.length > 1) { String type = values[0]; String unit = values[1]; Weather.setUnits(unit); if(type.equals("combo")) { weatherNotificationEnabled = true; weatherClockEnabled = true; } else if(type.equals("notification")) { weatherNotificationEnabled = true; weatherClockEnabled = false; } else if(type.equals("clock")) { weatherClockEnabled = true; weatherNotificationEnabled = false; } } else { weatherNotificationEnabled = true; weatherClockEnabled = true; } } } public void startGoogleApiClient() { Log.d(LOG_TAG, "startGoogleApiClient"); gFit = new GoogleFit(this); } public void startFitnessSync(ArrayList<PedometerData> pedometerList, ArrayList<ExerciseData> exerciseList, ArrayList<SleepData> sleepList, ArrayList<SleepInfo> sleepInfoList, ArrayList<HeartRateData> heartRateList, ProfileData pData) { Log.d(LOG_TAG, "startFitnessSync"); if(gFit != null) { Log.d(LOG_TAG, "gFit.setData"); gFit.setData(pedometerList, exerciseList, sleepList, sleepInfoList, heartRateList, pData); Log.d(LOG_TAG, "gFit.syncData"); gFit.syncData(); } else { Log.d(LOG_TAG, "Google Api Client not initialized"); } } public void sendTime(boolean is24Hour) { byte[] bytes = OpenFitApi.getCurrentTimeInfo(is24Hour); sendBluetoothBytes(bytes); } public void sendFitnessRequest() { Log.d(LOG_TAG, "sendFitnessRequest"); byte[] bytes = OpenFitApi.getFitnessRequest(); sendBluetoothBytes(bytes); } public void sendFitnessMenuResponse() { Log.d(LOG_TAG, "Fitness Menu"); byte[] bytes = OpenFitApi.getFitnessMenuResponse(); sendBluetoothBytes(bytes); } public void sendFitnessCycling() { Log.d(LOG_TAG, "Cycling"); } public void sendGPSReady() { byte[] bytes = OpenFitApi.getResponseGPSReady(); Log.d(LOG_TAG, "Sending GPS READY in hex: " + OpenFitApi.byteArrayToHexString(bytes) + " data len: " + (bytes.length - 5)); sendBluetoothBytes(bytes); } public void sendCurrentGPSData() { float tD = LocationInfo.getTotalDistance(); float cS = LocationInfo.getCurrentSpeed(); gpsData.computeExerciseResults(currentExerciseID); float cC = gpsData.getConsumedCalorie(); float cA = LocationInfo.getCurrentAltitude(); byte[] bytes = OpenFitApi.getResponseGPSData(tD, cS, cC, cA); Log.d(LOG_TAG, "Sending GPS DATA in hex: " + OpenFitApi.byteArrayToHexString(bytes) + " data len: " + (bytes.length - 5)); sendBluetoothBytes(bytes); } public void sendGPSResult() { gpsData.computeExerciseResults(currentExerciseID); float tD = gpsData.getTotalDistance(); float maxA = gpsData.getMaxAltitude(); float minA = gpsData.getMinAltitude(); float maxS = gpsData.getMaxSpeed(); float avgS = gpsData.getAverageSpeed(); float cC = gpsData.getConsumedCalorie(); float iD = gpsData.getInclineDistance(); float dD = gpsData.getDeclineDistance(); byte[] bytes = OpenFitApi.getResponseGPSResult(tD, maxA, minA, maxS, avgS, cC, iD, dD); Log.d(LOG_TAG, "Sending GPS RESULT in hex: " + OpenFitApi.byteArrayToHexString(bytes) + " data len: " + (bytes.length - 5)); sendBluetoothBytes(bytes); } public void sendSyncDone() { byte[] bytes = OpenFitApi.getResponseSyncDone(); Log.d(LOG_TAG, "Sending SYNC DONE in hex: " + OpenFitApi.byteArrayToHexString(bytes) + " data len: " + (bytes.length - 5)); sendBluetoothBytes(bytes); } public void sendGPSOFF() { byte[] bytes = OpenFitApi.getResponseGPSOFF(); Log.d(LOG_TAG, "Sending GPS OFF in hex: " + OpenFitApi.byteArrayToHexString(bytes) + " data len: " + (bytes.length - 5)); sendBluetoothBytes(bytes); } public void sendGPSON() { byte[] bytes = OpenFitApi.getResponseGPSON(); Log.d(LOG_TAG, "Sending GPS ON in hex: " + OpenFitApi.byteArrayToHexString(bytes) + " data len: " + (bytes.length - 5)); sendBluetoothBytes(bytes); } public void sendFitnessRunning() { Log.d(LOG_TAG, "Running"); } public void sendMediaTrack() { byte[] bytes = OpenFitApi.getOpenMediaTrack(MediaController.getTrack()); sendBluetoothBytes(bytes); } public void sendMediaPrev() { Log.d(LOG_TAG, "Media Prev"); sendBroadcast(MediaController.prevTrack(), null); } public void sendMediaNext() { Log.d(LOG_TAG, "Media Next"); sendBroadcast(MediaController.nextTrack(), null); } public void sendMediaPlay() { Log.d(LOG_TAG, "Media Play/Pause"); sendBroadcast(MediaController.playTrack(), null); } public void sendMediaVolume(byte vol, boolean req) { Log.d(LOG_TAG, "Media Volume: " + vol); byte offset = (byte) (MediaController.getActualVolume() - MediaController.getVolume()); if(offset != 0) { vol = (byte) (vol + offset); if(!req) { if(offset > 0) { vol += 1; } else { vol -= 1; } } } MediaController.setVolume(vol); byte[] bytes = OpenFitApi.getMediaSetVolume(vol); sendBluetoothBytes(bytes); } public void sendMediaRes() { Log.d(LOG_TAG, "Media Request"); sendMediaTrack(); sendMediaVolume(MediaController.getVolume(), true); } public void sendFindStart() { Log.d(LOG_TAG, "Find Start"); if(isFinding == false) { findSoundThread = new FindSoundThread(); findSoundThread.start(); isFinding = true; } } public void sendFindStop() { Log.d(LOG_TAG, "Find Stop"); if(findSoundThread != null) { findSoundThread = null; Log.d(LOG_TAG, "stopped find thread"); } isFinding = false; } public void sendAppNotification(String packageName, String sender, String title, String message, int id) { byte[] bytes = OpenFitApi.getOpenNotification(packageName, sender, title, message, id); sendBluetoothBytes(bytes); } public void sendEmailNotification(String packageName, String sender, String title, String message, int id) { byte[] bytes = OpenFitApi.getOpenEmail(sender, title, message, message, id); sendBluetoothBytes(bytes); } public void sendDialerNotification(String number) { long id = (long)(System.currentTimeMillis() / 1000L); String sender = number; String name = getContactName(number); if(name != null) { sender = name; } byte[] bytes = OpenFitApi.getOpenIncomingCall(sender, number, id); sendBluetoothBytes(bytes); } public void sendDialerEndNotification() { byte[] bytes = OpenFitApi.getOpenIncomingCallEnd(); sendBluetoothBytes(bytes); } public void endCall() { Log.d(LOG_TAG, "Ending call"); Class<?> telephonyClass = null; Method method = null; Method endCall = null; try { telephonyClass = Class.forName(telephony.getClass().getName()); method = telephonyClass.getDeclaredMethod("getITelephony"); method.setAccessible(true); Object iTelephony = null; iTelephony = method.invoke(telephony); endCall = iTelephony.getClass().getDeclaredMethod("endCall"); endCall.invoke(iTelephony); } catch(Exception e) { Log.d(LOG_TAG, "Failed ending call"); e.printStackTrace(); } } public void sendRejectMessage(String messageId, String phoneNumber) { StringBuilder updatedString = new StringBuilder(); for(int i = 0; i < messageId.length(); i++) { updatedString.append(messageId.charAt(i)); if(messageId.charAt(i) != '0') { break; } } int messageIdInt = Integer.parseInt(updatedString.toString(), 16); Log.d(LOG_TAG, "Reject message ID: " + messageId + ", " + messageIdInt); int msgSize = oPrefs.getInt("reject_messages_size"); if(msgSize > 0 && msgSize > messageIdInt) { Log.d(LOG_TAG, "Sending reject message: " + oPrefs.getString("reject_message_" + messageIdInt) + ", to: " + phoneNumber); try { SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(phoneNumber, null, oPrefs.getString("reject_message_" + messageIdInt), null, null); Toast.makeText(getApplicationContext(), R.string.toast_send_sms_success, Toast.LENGTH_SHORT).show(); } catch(Exception e) { Toast.makeText(getApplicationContext(), R.string.toast_send_sms_failed, Toast.LENGTH_SHORT).show(); Log.d(LOG_TAG, "Sending sms failed: " + e.toString()); } } } public void saveRejectMessagesToBracelet() { Log.d(LOG_TAG, "Sending reject messages to the bracelet"); int msgSize = oPrefs.getInt("reject_messages_size"); for(int i = 0; i < msgSize; i++) { byte[] bytes = OpenFitApi.getOpenRejectCallMessageForBracelet(msgSize, i, oPrefs.getString("reject_message_" + i)); sendBluetoothBytes(bytes); Log.d(LOG_TAG, "cnt = " + msgSize + ", id = " + i + ", msg = " + oPrefs.getString("reject_message_" + i)); } } public void sendSmsNotification(String number, String message) { long id = (long)(System.currentTimeMillis() / 1000L); String title = "Text Message"; String sender = number; String name = getContactName(number); if(name != null) { sender = name; } byte[] bytes = OpenFitApi.getOpenNotification(sender, number, title, message, id); sendBluetoothBytes(bytes); } public String getAppName(String packageName) { ApplicationInfo appInfo = null; try { appInfo = pManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA); } catch (NameNotFoundException e) { Log.d(LOG_TAG, "Cannot get application info"); } String appName = (String) pManager.getApplicationLabel(appInfo); return appName; } public String getContactName(String phoneNumber) { ContentResolver cr = this.getContentResolver(); Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); Cursor cursor = cr.query(uri, new String[] {PhoneLookup.DISPLAY_NAME}, null, null, null); if(cursor == null) { return null; } String contactName = null; if(cursor.moveToFirst()) { contactName = cursor.getString(cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME)); } if(cursor != null && !cursor.isClosed()) { cursor.close(); } return contactName; } public void sendAlarmStart() { long id = (long)(System.currentTimeMillis() / 1000L); byte[] bytes = OpenFitApi.getOpenAlarm(id); sendBluetoothBytes(bytes); } public void sendAlarmStop() { byte[] bytes = OpenFitApi.getOpenAlarmClear(); sendBluetoothBytes(bytes); } public void sendWeatherNotifcation(String weather, String icon) { long id = (long)(System.currentTimeMillis() / 1000L); byte[] bytes = OpenFitApi.getOpenWeather(weather, icon, id); sendBluetoothBytes(bytes); } public void sendWeatherClock(String location, String tempCur, String tempUnit, String icon) { byte[] bytes = OpenFitApi.getOpenWeatherClock(location, tempCur, tempUnit, icon); sendBluetoothBytes(bytes); } public void startCronJob() { Log.d(LOG_TAG, "Starting Cronjob"); Cronjob.start(); } public void stopCronJob() { Log.d(LOG_TAG, "Stopping Cronjob"); Cronjob.stop(); } public void getWeather() { if(LocationInfo.getLat() != 0 && LocationInfo.getLon() != 0) { String query = "lat=" + LocationInfo.getLat() + "&lon=" + LocationInfo.getLon(); String country = null; String location = null; if(LocationInfo.getCountryCode() != null) { country = LocationInfo.getCountryCode(); } else if(LocationInfo.getCountryName() != null) { country = LocationInfo.getCountryName(); } if(country != null) { location = LocationInfo.getCityName() + ", " + country; } else { location = LocationInfo.getCityName(); } Weather.getWeather(query, location); } } // Does not work /*public void snoozeAlarm() { Log.d(LOG_TAG, "Snoozing alarm"); Intent intent = Alarm.snoozeAlarm(); sendBroadcast(intent); } public void DismissAlarm() { Log.d(LOG_TAG, "Dismissing alarm"); Intent intent = Alarm.dismissAlarm(); sendBroadcast(intent); }*/ private BroadcastReceiver serviceStopReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(LOG_TAG, "Stopping Service"); reconnecting = false; isReconnect = false; isStopping = true; isFinding = false; mHandler = null; Log.d(LOG_TAG, "Stopping" + smsEnabled +" : " + phoneEnabled); if(smsEnabled) { unregisterReceiver(smsListener); unregisterReceiver(mmsListener); } if(phoneEnabled) { telephony.listen(dailerListener, PhoneStateListener.LISTEN_NONE); dailerListener.destroy(); } unregisterReceiver(btReceiver); unregisterReceiver(notificationReceiver); unregisterReceiver(smsReceiver); unregisterReceiver(mmsReceiver); unregisterReceiver(phoneReceiver); unregisterReceiver(phoneIdleReceiver); unregisterReceiver(phoneOffhookReceiver); unregisterReceiver(mediaReceiver); unregisterReceiver(alarmReceiver); unregisterReceiver(weatherReceiver); unregisterReceiver(locationReceiver); unregisterReceiver(cronReceiver); unregisterReceiver(googleFitReceiver); unregisterReceiver(billingReceiver); unregisterReceiver(saveRejectMessagesReceiver); unbindService(mServiceConnection); unbindService(billingServiceConnection); Cronjob.stop(); clearNotification(); reconnectBluetoothStop(); Log.d(LOG_TAG, "stopSelf"); stopForeground(true); stopSelf(); } }; private BroadcastReceiver btReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String message = intent.getStringExtra("message"); handleUIMessage(message, intent); Log.d(LOG_TAG, "Received UI Command: " + message); } }; private BroadcastReceiver notificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String packageName = intent.getStringExtra("packageName"); final String ticker = intent.getStringExtra("ticker"); final String title = intent.getStringExtra("title"); final String message = intent.getStringExtra("message"); //long time = intent.getLongExtra("time", 0); final int id = intent.getIntExtra("id", 0); final String appName = getAppName(packageName); if(packageName.equals("com.google.android.gm")) { Log.d(LOG_TAG, "Received email:" + appName + " title:" + title + " ticker:" + ticker + " message:" + message); sendEmailNotification(appName, title, ticker, message, id); } else if(packageName.equals("com.android.calendar")) { Log.d(LOG_TAG, "Received calendar: " + appName + " Title:" + title + " Alarm time:"+message); final String caltitle = getString(R.string.calendar_event) + ": " + title + "\n" + getString(R.string.calendar_when) + ": " + message; sendAppNotification(appName, message, ticker, caltitle, id); } else { Log.d(LOG_TAG, "Received notification appName: " + appName + " title:" + title + " ticker:" + ticker + " message:" + message); sendAppNotification(appName, title, ticker, message, id); } } }; private BroadcastReceiver smsReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String message = intent.getStringExtra("message"); String sender = intent.getStringExtra("sender"); Log.d(LOG_TAG, "Recieved SMS message: " + sender + " - " + message); sendSmsNotification(sender, message); } }; private BroadcastReceiver mmsReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String message = "MMS received"; String sender = intent.getStringExtra("sender"); Log.d(LOG_TAG, "Recieved MMS message: "+sender+" - "+message); sendSmsNotification(sender, message); } }; private BroadcastReceiver phoneReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String sender = intent.getStringExtra("sender"); Log.d(LOG_TAG, "Recieved PHONE: "+sender); lastPhoneNumber = sender; sendDialerNotification(sender); } }; private BroadcastReceiver phoneIdleReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String sender = intent.getStringExtra("sender"); Log.d(LOG_TAG, "Recieved Idle: "+sender); sendDialerEndNotification(); } }; private BroadcastReceiver phoneOffhookReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String sender = intent.getStringExtra("sender"); Log.d(LOG_TAG, "Recieved Offhook: "+sender); sendDialerEndNotification(); } }; private BroadcastReceiver mediaReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String mediaTrack = intent.getStringExtra("mediaTrack"); Log.d(LOG_TAG, "Media sending: " + mediaTrack); sendMediaTrack(); } }; private BroadcastReceiver alarmReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = Alarm.getAction(intent); Log.d(LOG_TAG, "Alarm Action: " + action); if(action.equals("START")) { sendAlarmStart(); } else if(action.equals("SNOOZE")) { sendAlarmStop(); } else if(action.equals("STOP")) { sendAlarmStop(); } } }; private BroadcastReceiver weatherReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(LOG_TAG, "weatherReceiver updated: "); //String name = intent.getStringExtra("name"); //String weather = intent.getStringExtra("weather"); String description = intent.getStringExtra("description"); String tempCur = intent.getStringExtra("tempCur"); //String tempMin = intent.getStringExtra("tempMin"); //String tempMax = intent.getStringExtra("tempMax"); String tempUnit = intent.getStringExtra("tempUnit"); //String humidity = intent.getStringExtra("humidity"); //String pressure = intent.getStringExtra("pressure"); String icon = intent.getStringExtra("icon"); String location = intent.getStringExtra("location"); String weatherInfo = location + ": " + tempCur + tempUnit + "\nWeather: " + description; Log.d(LOG_TAG, weatherInfo); if(weatherClockEnabled || weatherClockReq) { sendWeatherClock(location, tempCur, tempUnit, icon); } if(weatherNotificationEnabled) { sendWeatherNotifcation(weatherInfo, icon); } } }; private BroadcastReceiver locationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(LOG_TAG, "locationReceiver updated, locationForWeather: " + locationForWeather + ", locationForExercise: " + locationForExercise + ", checkGPSReady: " + checkGPSReady); if(locationForWeather || (!locationForExercise && !checkGPSReady)) { LocationInfo.removeUpdates(); } if(locationForWeather && (weatherClockEnabled || weatherNotificationEnabled)) { getWeather(); locationForWeather = false; } if(checkGPSReady) { currentExerciseID = gpsData.createExercise(currentExerciseType); sendGPSReady(); checkGPSReady = false; } if(locationForExercise) { if(currentExerciseID > -1) { //int id, float lon, float lat, float altitude, float totalDistance, float speed, float calories gpsData.insertExerciseData(currentExerciseID, LocationInfo.getLon(), LocationInfo.getLat(), LocationInfo.getCurrentAltitude(), LocationInfo.getTotalDistance(), LocationInfo.getCurrentSpeed(), LocationInfo.getTimestamp()); } if(locationForExerciseSubscribe) { sendCurrentGPSData(); } } } }; private BroadcastReceiver cronReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(LOG_TAG, "#####CronJob#####"); if(!locationForExercise && !checkGPSReady) { if((weatherClockEnabled || weatherNotificationEnabled)) { locationForWeather = true; LocationInfo.listenForLocation(true); } if(isPremium) { Log.d(LOG_TAG, "Premium Features"); if(googleFitEnabled) { googleFitSyncing = true; sendFitnessRequest(); } } } } }; private BroadcastReceiver googleFitReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String message = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_MSG); Log.d(LOG_TAG, "Received Google Fit: " + message); if(message.equals(OpenFitIntent.INTENT_GOOGLE_FIT)) { Boolean enabled = intent.getBooleanExtra(OpenFitIntent.INTENT_EXTRA_DATA, false); if(enabled) { Log.d(LOG_TAG, "Google Fit Enabled"); startGoogleApiClient(); googleFitEnabled = true; } else { Log.d(LOG_TAG, "Google Fit Disabled"); googleFitEnabled = false; } } if(message.equals(OpenFitIntent.INTENT_GOOGLE_FIT_SYNC)) { Log.d(LOG_TAG, "Google Fit Sync requested"); if(isPremium) { Log.d(LOG_TAG, "Premium Features"); if(googleFitEnabled) { googleFitSyncing = true; sendFitnessRequest(); } } else { Intent msg = new Intent(OpenFitIntent.INTENT_GOOGLE_FIT); msg.putExtra(OpenFitIntent.INTENT_EXTRA_MSG, OpenFitIntent.INTENT_GOOGLE_FIT_SYNC_STATUS); msg.putExtra(OpenFitIntent.INTENT_EXTRA_DATA, false); msg.putExtra(OpenFitIntent.INTENT_EXTRA_INFO, OpenFitIntent.INTENT_BILLING_NO_PURCHASE); sendBroadcast(msg); } } if(message.equals(OpenFitIntent.INTENT_GOOGLE_FIT_SYNC_STATUS)) { Boolean status = intent.getBooleanExtra(OpenFitIntent.INTENT_EXTRA_DATA, false); googleFitSyncing = false; if(status) { Log.d(LOG_TAG, "Google Fit Sync completed"); } else { Log.d(LOG_TAG, "Google Fit Sync failed"); } } } }; private BroadcastReceiver billingReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String message = intent.getStringExtra(OpenFitIntent.INTENT_EXTRA_MSG); Log.d(LOG_TAG, "Received Billing: "); if(message.equals(OpenFitIntent.INTENT_BILLING_VERIFIED)) { Boolean verified = intent.getBooleanExtra(OpenFitIntent.INTENT_EXTRA_DATA, false); if(verified) { Log.d(LOG_TAG, "Received Billing: "); isPremium = true; } else { isPremium = false; } } } }; private BroadcastReceiver saveRejectMessagesReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final Boolean save = intent.getBooleanExtra(OpenFitIntent.INTENT_EXTRA_DATA, false); Log.d(LOG_TAG, "Received reject messages save: " + save); if(save) { saveRejectMessagesToBracelet(); } } }; private class ReconnectBluetoothThread extends Thread { public void run() { long timeStart = Calendar.getInstance().getTimeInMillis(); Log.d(LOG_TAG, "Reconnecting Bluetooth: "+timeStart); while(reconnecting) { try { long timeDiff = Calendar.getInstance().getTimeInMillis() - timeStart; Log.d(LOG_TAG, "Reconnecting Elapsed time: " + timeDiff/1000); bluetoothLeService.connectRfcomm(); Thread.sleep(10000L); } catch(InterruptedException ie) { Thread.currentThread().interrupt(); return; } } } public void close() { reconnecting = false; } } private class FindSoundThread extends Thread { public void run() { long timeStart = Calendar.getInstance().getTimeInMillis(); Log.d(LOG_TAG, "FindSound Start: "+timeStart); ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, ToneGenerator.MAX_VOLUME); while(isFinding) { try { long timeDiff = Calendar.getInstance().getTimeInMillis() - timeStart; Log.d(LOG_TAG, "Sound time: " + timeDiff/1000); toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // 200 ms tone Thread.sleep(600L); } catch(InterruptedException ie) { Thread.currentThread().interrupt(); return; } } } }; }