com.iss.android.wearable.datalayer.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.iss.android.wearable.datalayer.MainActivity.java

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.iss.android.wearable.datalayer;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;

import com.google.android.gms.common.api.GoogleApiClient;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;

/**
 * The main activity with a view pager, containing three pages:<p/>
 * <ul>
 * <li>
 * Page 1: shows a list of DataItems received from the phone application
 * </li>
 * <li>
 * Page 2: shows the photo that is sent from the phone application
 * </li>
 * <li>
 * Page 3: includes two buttons to show the connected phone and watch devices
 * </li>
 * </ul>
 */
public class MainActivity extends Activity {

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static final int REQUEST_FINE_LOCATION = 1;
    private static final String[] PERMISSIONS_LOCATION = { Manifest.permission.ACCESS_FINE_LOCATION };
    private static final String TAG = "MainActivity";
    public static MainActivity itself;
    private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE };
    int current_time = 0;
    PendingIntent pendingInt = null;
    float heartbeat = 10;
    int steps = 1000;
    boolean allowHRM = false;
    private GoogleApiClient mGoogleApiClient;
    private Handler mHandler;
    private ArrayList<String> listItems = new ArrayList<String>();
    private ArrayAdapter<String> adapter;
    private Intent murderousIntent;
    private int warned = 0;
    BroadcastReceiver br = new BroadcastReceiver() {
        // Receives broadcasts sent from other points of the app, like the SensorsDataService
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(SensorsDataService.ACTION_BATTERY_STATUS)) {
                final TextView BatteryStatus = (TextView) findViewById(R.id.batteryLabel);
                int status = intent.getIntExtra(SensorsDataService.EXTRA_STATUS, 0);
                BatteryStatus.setText("HR: " + status + "%");
                // Checks if the Battery status is 15% or below and if the User already has been alarmed.
                // If the battery got charged up again, reset the Warning.
                if (status <= 15 && status > 10 && warned != 1) {
                    warned = 1;
                    displayBatteryWarning(warned);
                } else if (status <= 10 && status > 5 && warned != 2) {
                    warned = 2;
                    displayBatteryWarning(warned);
                } else if (status <= 5 && warned != 3) {
                    warned = 3;
                    displayBatteryWarning(warned);
                } else if (status > 15 && warned != 0) {
                    warned = 0;
                }
            } else if (intent.getAction().equals(SensorsDataService.ACTION_HR)) {
                // Prints out the heart rate
                final TextView HeartRate = (TextView) findViewById(R.id.heartRateLabel);
                int result = intent.getIntExtra(SensorsDataService.EXTRA_HR, 0);
                // Need to convert the Int to String or else the app crashes. GJ Google.
                HeartRate.setText(Integer.toString(result));
            } else if (intent.getAction().equals(SensorsDataService.UPDATE_GPS_PARAMS)) {
                // Prints out the heart rate
            } else if (intent.getAction().equals(SensorsDataService.ASK_USER_FOR_RPE)) {
                CheckToShowRPE();
            } else if (intent.getAction().equals(SensorsDataService.NEW_MESSAGE_AVAILABLE)) {
                // prints out the Outputevent messages
                final TextView MessageLabel = (TextView) findViewById(R.id.messageLabel);
                String message = intent.getStringExtra("message");
                MessageLabel.setText(message);
            } else if (intent.getAction().equals(SensorsDataService.UPDATE_TIMER_VALUE)) {
                String newtime = String.valueOf(intent.getIntExtra("minutes", 0)) + ":"
                        + StringUtils.leftPad(Long.toString(intent.getIntExtra("seconds", 0)), 2, "0");
                TextView timetext = (TextView) findViewById(R.id.timer);
                timetext.setText(newtime);
            }

            showCurrentAppState();

        }
    };
    private DataUpdateReceiver dataUpdateReceiver;

    public static Context getContext() {
        return itself;
    }

    @Override
    public void onCreate(Bundle b) {

        super.onCreate(b);
        itself = this;

        // needs to be the first thing to happen
        initializeSelfRestarting();

        mHandler = new Handler();
        setContentView(R.layout.main_activity);

        initializeSWBatteryChecker();

        RegisterBroadcastsReceiver();

        CheckToShowRPE();

        CheckPermissions();

    }

    private void CheckPermissions() {
        int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
        }

        permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(this, PERMISSIONS_LOCATION, REQUEST_FINE_LOCATION);
        }
    }

    void CheckToShowRPE() {

        if (SensorsDataService.itself == null) {
            return;
        }

        if (!SensorsDataService.itself.needToShowRPE) {
            return;
        }

        SensorsDataService.itself.needToShowRPE = false;

    }

    // Updates the app state shown through the interface
    private void showCurrentAppState() {

        if (SensorsDataService.itself == null) {
            return;
        }

        // get measured states
        HashMap<String, Boolean> recordedActivities = SensorsDataService.getRecordedActivities();

        ImageButton morningHR = (ImageButton) findViewById(R.id.morningHR);
        ImageButton trainingHR = (ImageButton) findViewById(R.id.trainingHR);
        ImageButton startCooldown = (ImageButton) findViewById(R.id.startCooldown);
        ImageButton continueCooldown = (ImageButton) findViewById(R.id.continueCooldown);
        ImageButton eveningHR = (ImageButton) findViewById(R.id.eveningHR);

        morningHR.setBackgroundColor(recordedActivities.containsKey("MorningHR") ? Color.GREEN : Color.GRAY);
        trainingHR.setBackgroundColor(recordedActivities.containsKey("TrainingHR") ? Color.GREEN : Color.GRAY);
        startCooldown.setBackgroundColor(recordedActivities.containsKey("Cooldown") ? Color.GREEN : Color.GRAY);
        continueCooldown.setBackgroundColor(recordedActivities.containsKey("Recovery") ? Color.GREEN : Color.GRAY);
        eveningHR.setBackgroundColor(recordedActivities.containsKey("EveningHR") ? Color.GREEN : Color.GRAY);

        int inProgressColor = Color.argb(255, 255, 165, 0);

        if (SensorsDataService.itself.currentState.equals("Cooldown")) {
            startCooldown.setBackgroundColor(inProgressColor);
        }
        if (SensorsDataService.itself.currentState.equals("TrainingHR")) {
            trainingHR.setBackgroundColor(inProgressColor);
        }
        if (SensorsDataService.itself.currentState.equals("Recovery")) {
            continueCooldown.setBackgroundColor(inProgressColor);
        }
        if (SensorsDataService.itself.currentState.equals("MorningHR")) {
            morningHR.setBackgroundColor(inProgressColor);
        }
        if (SensorsDataService.itself.currentState.equals("EveningHR")) {
            eveningHR.setBackgroundColor(inProgressColor);
        }
    }

    // If the app crashes, restart it. Currently disabled so we can bugfix
    private void initializeSelfRestarting() {

        pendingInt = PendingIntent.getActivity(this, 0, new Intent(getIntent()), getIntent().getFlags());
        // Intent that kills the app after a certain amount of time after the app has crashed
        murderousIntent = new Intent(this, SensorsDataService.class);
        // start handler which starts pending-intent after Application Crash
        /*Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
            Log.d("Killer", "kills");
            // something went wrong ... this cannot continue like this anymore ...
            // we need to start everything from scratch ...
            AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 10000, pendingInt);
            // under the circumstances I have no choice but to murder the service and the app itself ...
            // put it out of its misery ...
            stopService(murderousIntent);
            android.os.Process.killProcess(android.os.Process.myPid());
            // It will hunt me until the end of my days in my nightmares...
            // My darkest secret, slowly eating on my soul and driving me mad ...
            System.exit(2);
            
        }
        });/**/

    }

    // Handles received broadcasted intents
    private void RegisterBroadcastsReceiver() {

        IntentFilter filter = new IntentFilter();
        filter.addAction(SensorsDataService.ACTION_BATTERY_STATUS);
        filter.addAction(SensorsDataService.ACTION_HR);
        filter.addAction(SensorsDataService.NEW_MESSAGE_AVAILABLE);
        filter.addAction(SensorsDataService.ASK_USER_FOR_RPE);
        filter.addAction(SensorsDataService.UPDATE_TIMER_VALUE);
        filter.addAction(SensorsDataService.UPDATE_GPS_PARAMS);
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        registerReceiver(br, filter);

    }

    // initialises a battery checker for the smartwatch
    private void initializeSWBatteryChecker() {
        final TextView SWBatteryStatus = (TextView) findViewById(R.id.SWbatteryLabel);
        final Handler h = new Handler();
        final int delay = 20000; //milliseconds
        final boolean[] warned_evening = { false };

        // Timer's fine for Java, but kills android apps.

        h.postDelayed(new Runnable() {
            public void run() {
                IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
                Intent batteryStatus = registerReceiver(null, ifilter);

                int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

                int batteryPct = (int) (level / (float) scale * 100);
                SWBatteryStatus.setText("SW: " + batteryPct + "%");
                Calendar clnd = Calendar.getInstance();
                if (clnd.get(Calendar.HOUR_OF_DAY) >= 20) {
                    if (batteryPct < 75 && !warned_evening[0]) {
                        warned_evening[0] = true;
                        displaySWBatteryWarning();
                    } else if (batteryPct >= 75 && warned_evening[0]) {
                        warned_evening[0] = false;
                    }
                }
                h.postDelayed(this, delay);
            }
        }, 0);
    }

    // Displays a battery warning if it is to be assumed the battery won't last until dawn
    private void displaySWBatteryWarning() {
        // Display a cancelable warning that the HRM battery is running low.
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        String warning = "The Smartwatch battery charge is below 75%. Please charge it to ensure it lasts the night.";
        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        v.vibrate(100);
        builder.setMessage(warning).setTitle(R.string.battery_warning_title).setCancelable(true)
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

        AlertDialog dialog = builder.create();
        dialog.show();
    }

    // displays a battery warning if the battery is low
    private void displayBatteryWarning(int warned) {
        // Display a cancelable warning that the HRM battery is running low.
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        String warning = "";
        switch (warned) {
        case 1:
            warning = "HRM Battery Level at 15%";
            break;
        case 2:
            warning = "HRM Battery Level at 10%";
            break;
        case 3:
            warning = "HRM Battery Level at 5%";
            break;
        }
        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        v.vibrate(100);
        builder.setMessage(warning).setTitle(R.string.battery_warning_title).setCancelable(true)
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                        dialog.dismiss();
                    }
                });

        AlertDialog dialog = builder.create();
        dialog.setCancelable(true);
        dialog.show();
    }

    @Override
    protected void onResume() {
        super.onResume();

        // restart of the dataservice retrieving data from the sensor

        if (SensorsDataService.itself == null) {
            Intent intent = new Intent(this, SensorsDataService.class);
            startService(intent);
        }

        //mGoogleApiClient.connect();
        if (dataUpdateReceiver == null)
            dataUpdateReceiver = new DataUpdateReceiver();
        IntentFilter intentFilter = new IntentFilter(SensorsDataService.NEW_MESSAGE_AVAILABLE);
        registerReceiver(dataUpdateReceiver, intentFilter);

        /*if (SensorsDataService.itself != null){
        SensorsDataService.itself.StopSleepTracking();
        }*/

        RegisterBroadcastsReceiver();

        showCurrentAppState();

    }

    @Override
    protected void onPause() {
        super.onPause();
        /*Wearable.DataApi.removeListener(mGoogleApiClient, this);
        Wearable.MessageApi.removeListener(mGoogleApiClient, this);
        Wearable.NodeApi.removeListener(mGoogleApiClient, this);
        mGoogleApiClient.disconnect();*/
        //mSensorManager.unregisterListener(this);
        if (br != null)
            unregisterReceiver(br);

    }

    public void onClicked(View view) {
        switch (view.getId()) {
        case R.id.morningHR:

            if (SensorsDataService.itself != null) {

                if (!SensorsDataService.isNowASleepingHour())
                    SensorsDataService.itself.SwitchSportsAction("MorningHR");
            }

            break;
        case R.id.trainingHR:

            if (SensorsDataService.itself != null) {
                SensorsDataService.itself.SwitchSportsAction("TrainingHR");
            }

            break;
        case R.id.startCooldown:

            if (SensorsDataService.itself != null) {
                SensorsDataService.itself.SwitchSportsAction("Cooldown");
            }

            break;
        case R.id.continueCooldown:

            if (SensorsDataService.itself != null) {
                SensorsDataService.itself.SwitchSportsAction("Recovery");
            }

            break;
        case R.id.eveningHR:

            if (SensorsDataService.itself != null) {
                if (SensorsDataService.isNowASleepingHour())
                    SensorsDataService.itself.SwitchSportsAction("EveningHR");
            }

            break;
        case R.id.searchForHRM:
            try {
                final Intent bluetoothSelector = new Intent(this, DeviceScanActivity.class);
                startActivity(bluetoothSelector);
            } catch (Exception ex) {
                Log.e(TAG, ex.toString());
            }
            break;
        default:

            Log.e(TAG, "Unknown click event registered");
        }

        showCurrentAppState();

    }

    // this is used to communicate with Service
    private class DataUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(SensorsDataService.NEW_MESSAGE_AVAILABLE)) {
                //UpdateButtonText was called from here, but  that method didn't do anything.
            }

        }
    }
}