uk.org.openseizuredetector.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for uk.org.openseizuredetector.MainActivity.java

Source

/*
  Pebble_sd - a simple accelerometer based seizure detector that runs on a
  Pebble smart watch (http://getpebble.com).
    
  See http://openseizuredetector.org for more information.
    
  Copyright Graham Jones, 2015.
    
  This file is part of pebble_sd.
    
  Pebble_sd is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
      
  Pebble_sd is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
      
  You should have received a copy of the GNU General Public License
  along with pebble_sd.  If not, see <http://www.gnu.org/licenses/>.
    
*/

package uk.org.openseizuredetector;

import android.app.ActionBar;
import android.app.Activity;
import android.app.IntentService;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
import android.preference.Preference;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.Context;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Button;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.conn.util.InetAddressUtils;
import java.lang.CharSequence;
import android.util.AttributeSet;

//MPAndroidChart
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.Legend.LegendForm;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.DataSet;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.data.filter.Approximator;
import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType;
import com.github.mikephil.charting.listener.OnChartGestureListener;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.Highlight;

import uk.org.openseizuredetector.SdServer;

public class MainActivity extends Activity {
    static final String TAG = "MainActivity";
    private int okColour = Color.BLUE;
    private int warnColour = Color.MAGENTA;
    private int alarmColour = Color.RED;
    SdServer mSdServer;
    boolean mBound = false;
    private Menu mOptionsMenu;

    private Intent sdServerIntent;

    final Handler serverStatusHandler = new Handler();
    Messenger messenger = new Messenger(new ResponseHandler());

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Initialise the User Interface
        setContentView(R.layout.main);

        /* Force display of overflow menu - from stackoverflow
         * "how to force use of..."
         */
        try {
            ViewConfiguration config = ViewConfiguration.get(this);
            Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
            if (menuKeyField != null) {
                menuKeyField.setAccessible(true);
                menuKeyField.setBoolean(config, false);
            }
        } catch (Exception e) {
            Log.v(TAG, "menubar fiddle exception: " + e.toString());
        }

        // start timer to refresh user interface every second.
        Timer uiTimer = new Timer();
        uiTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                updateServerStatus();
            }
        }, 0, 1000);

    }

    /**
     * Create Action Bar
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_activity_actions, menu);
        mOptionsMenu = menu;
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Log.v(TAG, "Option " + item.getItemId() + " selected");
        switch (item.getItemId()) {
        case R.id.action_launch_pebble_app:
            Log.v(TAG, "action_launch_pebble_app");
            try {
                PackageManager pm = this.getPackageManager();
                Intent pebbleAppIntent = pm.getLaunchIntentForPackage("com.getpebble.android");
                this.startActivity(pebbleAppIntent);
            } catch (Exception ex) {
                Log.v(TAG, "exception starting pebble App " + ex.toString());
            }
            return true;
        case R.id.action_start_stop:
            // Respond to the start/stop server menu item.
            Log.v(TAG, "action_sart_stop");
            if (mBound) {
                Log.v(TAG, "Stopping Server");
                unbindFromServer();
                stopServer();
            } else {
                Log.v(TAG, "Starting Server");
                startServer();
                // and bind to it so we can see its data
                bindToServer();
            }
            return true;
        case R.id.action_test_fault_beep:
            Log.v(TAG, "action_test_fault_beep");
            if (mBound) {
                mSdServer.faultWarningBeep();
            }
            return true;
        case R.id.action_test_alarm_beep:
            Log.v(TAG, "action_test_alarm_beep");
            if (mBound) {
                mSdServer.alarmBeep();
            }
            return true;
        case R.id.action_test_warning_beep:
            Log.v(TAG, "action_test_warning_beep");
            if (mBound) {
                mSdServer.warningBeep();
            }
            return true;
        case R.id.action_test_sms_alarm:
            Log.v(TAG, "action_test_sms_alarm");
            if (mBound) {
                mSdServer.sendSMSAlarm();
            }
            return true;
        case R.id.action_settings:
            Log.v(TAG, "action_settings");
            try {
                Intent prefsIntent = new Intent(MainActivity.this, PrefActivity.class);
                this.startActivity(prefsIntent);
            } catch (Exception ex) {
                Log.v(TAG, "exception starting settings activity " + ex.toString());
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        boolean audibleAlarm = SP.getBoolean("AudibleAlarm", true);
        Log.v(TAG, "onStart - auidbleAlarm = " + audibleAlarm);

        TextView tv;
        tv = (TextView) findViewById(R.id.versionTv);
        String versionName = "unknown";
        // From http://stackoverflow.com/questions/4471025/
        //         how-can-you-get-the-manifest-version-number-
        //         from-the-apps-layout-xml-variable
        final PackageManager packageManager = getPackageManager();
        if (packageManager != null) {
            try {
                PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0);
                versionName = packageInfo.versionName;
            } catch (PackageManager.NameNotFoundException e) {
                Log.v(TAG, "failed to find versionName");
                versionName = null;
            }
        }
        tv.setText("OpenSeizureDetector Server Version " + versionName);

        if (!isServerRunning()) {
            Log.v(TAG, "Server not Running - Starting Server");
            startServer();
        } else {
            Log.v(TAG, "Server Already Running OK");
        }
        // and bind to it so we can see its data
        bindToServer();

    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindFromServer();
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            SdServer.SdBinder binder = (SdServer.SdBinder) service;
            mSdServer = binder.getService();
            mBound = true;
            if (mSdServer != null) {
                Log.v(TAG, "onServiceConnected() - Asking server to update its settings");
                mSdServer.updatePrefs();
            } else {
                Log.v(TAG, "onServiceConnected() - mSdServer is null - this is wrong!");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            Log.v(TAG, "onServiceDisonnected()");
            mBound = false;
        }
    };

    /**
     * bind to an already running server.
     */
    private void bindToServer() {
        Log.v(TAG, "bindToServer() - binding to SdServer");
        Intent intent = new Intent(this, SdServer.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    /** 
     * unbind from server
     */
    private void unbindFromServer() {
        // unbind this activity from the service if it is bound.
        if (mBound) {
            Log.v(TAG, "unbindFromServer() - unbinding");
            try {
                unbindService(mConnection);
                mBound = false;
            } catch (Exception ex) {
                Log.e(TAG, "unbindFromServer() - error unbinding service - " + ex.toString());
            }
        } else {
            Log.v(TAG, "unbindFromServer() - not bound to server - ignoring");
        }
    }

    /**
     * Start the SdServer service
     */
    private void startServer() {
        // Start the server
        sdServerIntent = new Intent(MainActivity.this, SdServer.class);
        sdServerIntent.setData(Uri.parse("Start"));
        getApplicationContext().startService(sdServerIntent);

        // Change the action bar icon to show the option to stop the service.
        if (mOptionsMenu != null) {
            Log.v(TAG, "Changing menu icons");
            MenuItem menuItem = mOptionsMenu.findItem(R.id.action_start_stop);
            menuItem.setIcon(R.drawable.stop_server);
            menuItem.setTitle("Stop Server");
        } else {
            Log.v(TAG, "mOptionsMenu is null - not changing icons!");
        }
    }

    /**
     * Stop the SdServer service
     */
    private void stopServer() {
        Log.v(TAG, "stopping Server...");

        // then send an Intent to stop the service.
        sdServerIntent = new Intent(MainActivity.this, SdServer.class);
        sdServerIntent.setData(Uri.parse("Stop"));
        getApplicationContext().stopService(sdServerIntent);

        // Change the action bar icon to show the option to start the service.
        if (mOptionsMenu != null) {
            Log.v(TAG, "Changing action bar icons");
            mOptionsMenu.findItem(R.id.action_start_stop).setIcon(R.drawable.start_server);
            mOptionsMenu.findItem(R.id.action_start_stop).setTitle("Start Server");
        } else {
            Log.v(TAG, "mOptionsMenu is null, not changing icons!");
        }

    }

    /**
     * Based on http://stackoverflow.com/questions/7440473/android-how-to-check-if-the-intent-service-is-still-running-or-has-stopped-running
     */
    public boolean isServerRunning() {
        //Log.v(TAG,"isServerRunning()................");
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            //Log.v(TAG,"Service: "+service.service.getClassName());
            if ("uk.org.openseizuredetector.SdServer".equals(service.service.getClassName())) {
                //Log.v(TAG,"Yes!");
                return true;
            }
        }
        //Log.v(TAG,"No!");
        return false;
    }

    /** get the ip address of the phone.
     * Based on http://stackoverflow.com/questions/11015912/how-do-i-get-ip-address-in-ipv4-format
     */
    public String getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en
                    .hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    //Log.v(TAG,"ip1--:" + inetAddress);
                    //Log.v(TAG,"ip2--:" + inetAddress.getHostAddress());

                    // for getting IPV4 format
                    if (!inetAddress.isLoopbackAddress()
                            && InetAddressUtils.isIPv4Address(inetAddress.getHostAddress())) {

                        String ip = inetAddress.getHostAddress().toString();
                        //Log.v(TAG,"ip---::" + ip);
                        return ip;
                    }
                }
            }
        } catch (Exception ex) {
            Log.e("IP Address", ex.toString());
        }
        return null;
    }

    /*
     * updateServerStatus - called by the uiTimer timer periodically.
     * requests the ui to be updated by calling serverStatusRunnable.
     */
    private void updateServerStatus() {
        serverStatusHandler.post(serverStatusRunnable);
    }

    /*
     * serverStatusRunnable - called by updateServerStatus - updates the
     * user interface to reflect the current status received from the server.
     */
    final Runnable serverStatusRunnable = new Runnable() {
        public void run() {
            TextView tv;
            tv = (TextView) findViewById(R.id.textView1);
            if (isServerRunning()) {
                tv.setText("Server Running OK");
                tv.setBackgroundColor(okColour);
                tv = (TextView) findViewById(R.id.textView2);
                tv.setText("Access Server at http://" + getLocalIpAddress() + ":8080");
                tv.setBackgroundColor(okColour);
            } else {
                tv.setText("*** Server Stopped ***");
                tv.setBackgroundColor(alarmColour);
            }

            try {
                if (mBound) {
                    tv = (TextView) findViewById(R.id.alarmTv);
                    if (mSdServer.sdData.alarmState == 0) {
                        tv.setText(mSdServer.sdData.alarmPhrase);
                        tv.setBackgroundColor(okColour);
                    }
                    if (mSdServer.sdData.alarmState == 1) {
                        tv.setText(mSdServer.sdData.alarmPhrase);
                        tv.setBackgroundColor(warnColour);
                    }
                    if (mSdServer.sdData.alarmState == 2) {
                        tv.setText(mSdServer.sdData.alarmPhrase);
                        tv.setBackgroundColor(alarmColour);
                    }
                    tv = (TextView) findViewById(R.id.pebTimeTv);
                    tv.setText(mSdServer.mPebbleStatusTime.format("%H:%M:%S"));
                    // Pebble Connected Phrase
                    tv = (TextView) findViewById(R.id.pebbleTv);
                    if (mSdServer.sdData.pebbleConnected) {
                        tv.setText("Pebble Watch Connected OK");
                        tv.setBackgroundColor(okColour);
                    } else {
                        tv.setText("** Pebble Watch NOT Connected **");
                        tv.setBackgroundColor(alarmColour);
                    }
                    tv = (TextView) findViewById(R.id.appTv);
                    if (mSdServer.sdData.pebbleAppRunning) {
                        tv.setText("Pebble App OK");
                        tv.setBackgroundColor(okColour);
                    } else {
                        tv.setText("** Pebble App NOT Running **");
                        tv.setBackgroundColor(alarmColour);
                    }
                    tv = (TextView) findViewById(R.id.battTv);
                    tv.setText("Pebble Battery = " + String.valueOf(mSdServer.sdData.batteryPc) + "%");
                    if (mSdServer.sdData.batteryPc <= 20)
                        tv.setBackgroundColor(alarmColour);
                    if (mSdServer.sdData.batteryPc > 20)
                        tv.setBackgroundColor(warnColour);
                    if (mSdServer.sdData.batteryPc >= 40)
                        tv.setBackgroundColor(okColour);

                    tv = (TextView) findViewById(R.id.debugTv);
                    String specStr = "";
                    for (int i = 0; i < 10; i++)
                        specStr = specStr + mSdServer.sdData.simpleSpec[i] + ", ";
                    tv.setText("Spec = " + specStr);
                } else {
                    tv = (TextView) findViewById(R.id.alarmTv);
                    tv.setText("Not Connected to Server");
                    tv.setBackgroundColor(warnColour);
                }
            } catch (Exception e) {
                Log.v(TAG, "ServerStatusRunnable: Exception - " + e.toString());
            }
            ////////////////////////////////////////////////////////////
            // Produce graph
            LineChart mChart = (LineChart) findViewById(R.id.chart1);
            mChart.setDescription("");
            mChart.setNoDataTextDescription("You need to provide data for the chart.");
            // X Values
            ArrayList<String> xVals = new ArrayList<String>();
            for (int i = 0; i < 10; i++) {
                xVals.add((i) + "");
            }
            // Y Values
            ArrayList<Entry> yVals = new ArrayList<Entry>();
            for (int i = 0; i < 10; i++) {
                if (mSdServer != null)
                    yVals.add(new Entry(mSdServer.sdData.simpleSpec[i], i));
                else
                    yVals.add(new Entry(i, i));
            }

            // create a dataset and give it a type
            LineDataSet set1 = new LineDataSet(yVals, "DataSet 1");
            set1.setColor(Color.BLACK);
            set1.setLineWidth(1f);

            ArrayList<LineDataSet> dataSets = new ArrayList<LineDataSet>();
            dataSets.add(set1); // add the datasets
            LineData data = new LineData(xVals, dataSets);
            //data.setValueTextSize(10f);
            mChart.setData(data);
            mChart.invalidate();
        }
    };

    @Override
    protected void onPause() {
        super.onPause();
    }

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

    //public void updateUi() {
    //   String statusPhrase;
    //   String alarmPhrase;
    //   String viewText = "Unknown";
    //}

    class ResponseHandler extends Handler {
        @Override
        public void handleMessage(Message message) {
            Log.v(TAG, "Message=" + message.toString());
        }
    }

}