diff --git a/CHANGELOG.md b/CHANGELOG.md index 4df3012..96e5348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ OpenSeizureDetector Android App - Change Log ============================================ - V2.6.0 - 01 Sep 2017 - Added Support for Wifi data source (initially to be used for ESP8266_SD) - and Android Wear datasource + V2.6.0 - 26dec2018 + - Changed SMS code to comply with new Google Play Store requirements. + - Added Support for Wifi data source (initially to be used for Garmin_SD) + + V2.5.5 - 23feb2018 - Improved logging to help diagnose network problems + that result in 'net fault' warnings from network data source + ('wifi-storms'). V2.5.4 - 03dec2017 - Added option to use either tone generator or MP3 alarm sound, as a user reported problem with tone generator on high end samsung phone. diff --git a/DEV_NOTES.txt b/DEV_NOTES.txt new file mode 100644 index 0000000..289bdb1 --- /dev/null +++ b/DEV_NOTES.txt @@ -0,0 +1,14 @@ +Graham's Development Notes +========================== + +V2.6 +- We had a V2.6 started, but I can't remember what it did (but it does include + the NetworkPassive Datasource that I want). +- Start V2.6_new to add in the changes needed for SMS. +- Merge V2.6_new into V2.6, and resolve conflicts. +- Change the gradle dependencies from 'compile' to 'implementation' to get rid + of build warnings. +- clean project and re-build. +- Suddenly got an error "com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: + The number of method references in a .dex file cannot exceed 64K." +- Added multidex support library to build.gradle dependencies and it seemed to compile.... diff --git a/app/build.gradle b/app/build.gradle index a871cfd..838e273 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,22 +23,23 @@ android { } dependencies { - compile files('libs/mpandroidchartlibrary-2-0-7.jar') - compile 'com.getpebble:pebblekit:3.1.0@aar' + implementation 'com.android.support:multidex:1.0.3' + implementation files('libs/mpandroidchartlibrary-2-0-7.jar') + implementation 'com.getpebble:pebblekit:3.1.0@aar' // Unit testing dependencies - testCompile 'junit:junit:4.12' + testImplementation 'junit:junit:4.12' // Set this dependency if you want to use Mockito - testCompile 'org.mockito:mockito-core:1.10.19' + testImplementation 'org.mockito:mockito-core:1.10.19' // Set this dependency if you want to use Hamcrest matching - testCompile 'org.hamcrest:hamcrest-library:1.1' - compile 'com.android.support:appcompat-v7:22.2.1' - compile 'com.android.support:support-v4:22.2.1' + testImplementation 'org.hamcrest:hamcrest-library:1.1' + implementation 'com.android.support:appcompat-v7:22.2.1' + implementation 'com.android.support:support-v4:22.2.1' //compile files('libs/JTransforms-3.1-with-dependencies.jar') - compile 'org.apache.commons:commons-math3:3.6.1' + implementation 'org.apache.commons:commons-math3:3.6.1' // google play services used for location finding for SMS alerts. - compile 'com.google.android.gms:play-services-location:10.0.0' - compile 'com.google.android.gms:play-services:10.0.1' - compile 'com.github.wendykierp:JTransforms:3.0' + implementation 'com.google.android.gms:play-services:10.0.1' + implementation 'com.github.wendykierp:JTransforms:3.0' + implementation 'com.google.android.gms:play-services-location:10.0.0' } diff --git a/app/release/app-release.apk b/app/release/app-release-2.5.5.apk similarity index 60% rename from app/release/app-release.apk rename to app/release/app-release-2.5.5.apk index db89ad3..f41b76f 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release-2.5.5.apk differ diff --git a/app/release/output.json b/app/release/output.json index 875bdfd..19a6650 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":38},"path":"app-release.apk","properties":{"packageId":"uk.org.openseizuredetector","split":"","minSdkVersion":"14"}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":41},"path":"app-release.apk","properties":{"packageId":"uk.org.openseizuredetector","split":"","minSdkVersion":"14"}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9c188c1..acce3c6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,12 @@ + diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetwork.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetwork.java index 98badba..12d776f 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetwork.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSourceNetwork.java @@ -28,6 +28,8 @@ public class SdDataSourceNetwork extends SdDataSource { private Time mStatusTime; private Timer mDataUpdateTimer; private int mDataUpdatePeriod = 2000; + private int mConnnectTimeoutPeriod = 5000; + private int mReadTimeoutPeriod = 5000; private String mServerIP = "unknown"; private int ALARM_STATE_NETFAULT = 7; @@ -92,6 +94,12 @@ public class SdDataSourceNetwork extends SdDataSource { String dataUpdatePeriodStr = SP.getString("DataUpdatePeriod","2000"); mDataUpdatePeriod = Integer.parseInt(dataUpdatePeriodStr); Log.v(TAG,"updatePrefs() - mDataUpdatePeriod = "+mDataUpdatePeriod); + String connectTimeoutPeriodStr = SP.getString("ConnectTimeoutPeriod","5000"); + mConnnectTimeoutPeriod = Integer.parseInt(connectTimeoutPeriodStr); + Log.v(TAG,"updatePrefs() - mConnectTimeoutPeriod = "+mConnnectTimeoutPeriod); + String readTimeoutPeriodStr = SP.getString("ReadTimeoutPeriod","5000"); + mReadTimeoutPeriod = Integer.parseInt(readTimeoutPeriodStr); + Log.v(TAG,"updatePrefs() - mReadTimeoutPeriod = "+mReadTimeoutPeriod); } catch (Exception ex) { Log.v(TAG,"updatePrefs() - Problem parsing preferences!"); mUtil.writeToSysLogFile("SdDataSourceNetwork().updatePrefs() - " +ex.toString()); @@ -156,9 +164,7 @@ public class SdDataSourceNetwork extends SdDataSource { } /** - * Retrive the current Seizure Detector Data from the server. - * Uses the DownloadSdDataTask class to download the data in the - * background. The data is processed in DownloadSdDataTask.onPostExecute(). + * Accept an alarm remotely using a http GET request. */ @Override public void acceptAlarm() { @@ -203,8 +209,8 @@ public class SdDataSourceNetwork extends SdDataSource { try { URL url = new URL(myurl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setReadTimeout(5000 /* milliseconds */); - conn.setConnectTimeout(5000 /* milliseconds */); + conn.setReadTimeout(mReadTimeoutPeriod /* milliseconds */); + conn.setConnectTimeout(mConnnectTimeoutPeriod /* milliseconds */); conn.setRequestMethod("GET"); conn.setDoInput(true); // Starts the query diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java index 77c69cf..1f758bb 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSourcePebble.java @@ -245,7 +245,7 @@ public class SdDataSourcePebble extends SdDataSource { */ public void updatePrefs() { Log.v(TAG, "updatePrefs()"); - mUtil.writeToSysLogFile("SdDataSourcePebble.updatePrefs()"); + //mUtil.writeToSysLogFile("SdDataSourcePebble.updatePrefs()"); SharedPreferences SP = PreferenceManager .getDefaultSharedPreferences(mContext); try { @@ -527,7 +527,7 @@ public class SdDataSourcePebble extends SdDataSource { */ public void getPebbleSdSettings() { Log.v(TAG, "getWatchSdSettings() - sending required settings to pebble"); - mUtil.writeToSysLogFile("SdDataSourcePebble.getWatchSdSettings()"); + //mUtil.writeToSysLogFile("SdDataSourcePebble.getPebbleSdSettings()"); sendPebbleSdSettings(); //Log.v(TAG, "getWatchSdSettings() - requesting settings from pebble"); //mUtil.writeToSysLogFile("SdDataSourcePebble.getWatchSdSettings() - and request settings from pebble"); @@ -545,7 +545,7 @@ public class SdDataSourcePebble extends SdDataSource { */ public void sendPebbleSdSettings() { Log.v(TAG, "sendPebblSdSettings() - preparing settings dictionary.. mSampleFreq=" + mSampleFreq); - mUtil.writeToSysLogFile("SdDataSourcePebble.sendWatchSdSettings()"); + //mUtil.writeToSysLogFile("SdDataSourcePebble.sendPebbleSdSettings()"); // Watch Settings final PebbleDictionary setDict = new PebbleDictionary(); diff --git a/app/src/main/java/uk/org/openseizuredetector/SdServer.java b/app/src/main/java/uk/org/openseizuredetector/SdServer.java index f1f0fad..aba4a1e 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdServer.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdServer.java @@ -41,6 +41,7 @@ import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.res.AssetManager; import android.content.SharedPreferences; import android.graphics.drawable.Drawable; @@ -48,6 +49,8 @@ import android.location.Location; import android.media.AudioManager; import android.media.RingtoneManager; import android.media.ToneGenerator; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; import android.net.Uri; import android.os.CountDownTimer; import android.os.Environment; @@ -124,6 +127,8 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei private Handler mHandler; private ToneGenerator mToneGenerator; + private NetworkBroadcastReceiver mNetworkBroadcastReceiver; + private final IBinder mBinder = new SdBinder(); /** @@ -554,12 +559,12 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei } else { if (mAudibleFaultWarning) { if (mMp3Alarm) { - Log.v(TAG,"making MP3 alarm beep"); + Log.v(TAG, "making MP3 alarm beep"); // From https://stackoverflow.com/questions/4441334/how-to-play-an-android-notification-sound // This plays an audio file as a notification, using the notification sound channel. NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - Uri soundUri = Uri.parse("android.resource://"+getPackageName()+"/raw/fault"); + Uri soundUri = Uri.parse("android.resource://" + getPackageName() + "/raw/fault"); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext()) .setSound(soundUri); //This sets the sound to play @@ -576,6 +581,7 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei } else { startFaultTimer(); Log.v(TAG, "faultWarningBeep() - starting Fault Timer"); + mUtil.writeToSysLogFile("faultWarningBeep() - starting Fault Timer"); } } @@ -590,15 +596,15 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei } else { if (mAudibleAlarm) { if (mMp3Alarm) { - Log.v(TAG,"making MP3 alarm beep"); + Log.v(TAG, "making MP3 alarm beep"); // From https://stackoverflow.com/questions/4441334/how-to-play-an-android-notification-sound // This plays an audio file as a notification, using the notification sound channel. NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - Uri soundUri = Uri.parse("android.resource://"+getPackageName()+"/raw/alarm"); + Uri soundUri = Uri.parse("android.resource://" + getPackageName() + "/raw/alarm"); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext()) - .setSound(soundUri); //This sets the sound to play + .setSound(soundUri); //This sets the sound to play notificationManager.notify(0, mBuilder.build()); } else { beep(3000); @@ -620,12 +626,12 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei } else { if (mAudibleWarning) { if (mMp3Alarm) { - Log.v(TAG,"making MP3 alarm beep"); + Log.v(TAG, "making MP3 alarm beep"); // From https://stackoverflow.com/questions/4441334/how-to-play-an-android-notification-sound // This plays an audio file as a notification, using the notification sound channel. NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - Uri soundUri = Uri.parse("android.resource://"+getPackageName()+"/raw/warning"); + Uri soundUri = Uri.parse("android.resource://" + getPackageName() + "/raw/warning"); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext()) .setSound(soundUri); //This sets the sound to play @@ -663,10 +669,19 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei Time tnow = new Time(Time.getCurrentTimezone()); tnow.setToNow(); String dateStr = tnow.format("%H:%M:%S %d/%m/%Y"); - SmsManager sm = SmsManager.getDefault(); + // SmsManager sm = SmsManager.getDefault(); for (int i = 0; i < mSMSNumbers.length; i++) { Log.v(TAG, "sendSMSAlarm() - Sending to " + mSMSNumbers[i]); - sm.sendTextMessage(mSMSNumbers[i], null, mSMSMsgStr + " - " + dateStr, null, null); + // sm.sendTextMessage(mSMSNumbers[i], null, mSMSMsgStr + " - " + dateStr, null, null); + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setDataAndType(Uri.parse("smsto:"), "vnd.android-dir/mms-sms"); + intent.putExtra("sms_body", mSMSMsgStr + " - " + dateStr); + intent.putExtra("address", new String(mSMSNumbers[i])); + if (intent.resolveActivity(getPackageManager()) != null) { + startActivity(intent); + } else { + Log.v(TAG, "sendSMSAlarm() - Failed to send SMS."); + } } } else { Log.v(TAG, "sendSMSAlarm() - SMS Alarms Disabled - not doing anything!"); @@ -776,7 +791,7 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei // Start timer to remove the cancel audible flag // after the required period. if (mCancelAudibleTimer != null) { - Log.v(TAG, "onCreate(): cancel audible timer already running - cancelling it."); + Log.v(TAG, "cancelAudible(): cancel audible timer already running - cancelling it."); mCancelAudibleTimer.cancel(); mCancelAudibleTimer = null; mCancelAudible = false; @@ -804,7 +819,8 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei /** - * Start the web server (on port 8080) + * Start the web server (on port 8080), and register for network connectivity events so we can log + * problems. */ protected void startWebServer() { Log.v(TAG, "startWebServer()"); @@ -820,10 +836,16 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei } else { Log.v(TAG, "startWebServer(): server already running???"); } + + mNetworkBroadcastReceiver = new NetworkBroadcastReceiver(); + IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); + //filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + getApplicationContext().registerReceiver(mNetworkBroadcastReceiver, filter); } /** * Stop the web server - FIXME - doesn't seem to do anything! + * And de-register for network connectivity events. */ protected void stopWebServer() { Log.v(TAG, "SdServer.stopWebServer()"); @@ -836,8 +858,49 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei } webServer = null; } + getApplicationContext().unregisterReceiver(mNetworkBroadcastReceiver); } + private class NetworkBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + Log.v(TAG, "NetworkBroadCastReceiver.onReceive"); + //mUtil.writeToSysLogFile("Network State Changed" + intent.getAction()); + //mUtil.showToast("Network State Changed" + intent.getAction()); + + ConnectivityManager cm = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo activeNetwork = null; + try { + activeNetwork = cm.getActiveNetworkInfo(); + } catch (Exception e) { + Log.v(TAG, "NetworkBroadcastReceiver - failed to retrieve active network info"); + mUtil.writeToSysLogFile("NetworkBroadcastReceiver - failed to retrieve active network info"); + Log.v(TAG, e.toString()); + } + boolean isConnected = activeNetwork != null && + activeNetwork.isConnectedOrConnecting(); + if (isConnected) { + boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI; + if (!isWiFi) { + Log.v(TAG, "NetworkBroadcastReceiver - no Wifi Connection"); + mUtil.writeToSysLogFile("Network State Changed - no Wifi Connection"); + mUtil.showToast("Network State Changed - no Wifi Connection"); + } else { + Log.v(TAG, "NetworkBroadcastReceiver - Wifi Connected"); + mUtil.writeToSysLogFile("Network State Changed - Wifi Connected"); + mUtil.showToast("Network State Changed - Wifi Connected"); + } + } else { + Log.v(TAG, "NetworkBroadcastReceiver - No Active Network"); + mUtil.writeToSysLogFile("Network State Changed - No Active Network"); + mUtil.showToast("Network State Changed - No Active Network"); + } + } + } + + /** * Log data to SD card if mLogData is set in preferences. */ @@ -1022,8 +1085,10 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei public void startFaultTimer() { if (mFaultTimer != null) { Log.v(TAG, "startFaultTimer(): fault timer already running - not doing anything."); + mUtil.writeToSysLogFile("startFaultTimer() - fault timer already running"); } else { Log.v(TAG, "startFaultTimer(): starting fault timer."); + mUtil.writeToSysLogFile("startFaultTimer() - starting fault timer"); runOnUiThread(new Runnable() { public void run() { mFaultTimerCompleted = false; @@ -1039,11 +1104,13 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei public void stopFaultTimer() { if (mFaultTimer != null) { Log.v(TAG, "stopFaultTimer(): fault timer already running - cancelling it."); + mUtil.writeToSysLogFile("stopFaultTimer() - stopping fault timer"); mFaultTimer.cancel(); mFaultTimer = null; mFaultTimerCompleted = false; } else { Log.v(TAG, "stopFaultTimer(): fault timer not running - not doing anything."); + //mUtil.writeToSysLogFile("stopFaultTimer() - fault timer not running"); } } diff --git a/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java b/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java index 928cfa3..01f3992 100644 --- a/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java @@ -496,6 +496,8 @@ public class StartupActivity extends Activity { + "so I can get in touch if necessary.\nThank you! Graham \ngraham@openseizuredetector.org.uk " + "\n\nChanges in this version:" + "\n- Added support for 'Wifi Datasources' - initially for the experimental ESP8266 based seizure detector." + + "\n- Improved logging of network status to help debugging network data source issues." + + "\n- " ); // This makes the links display as links, but they do not respond to clicks for some reason... Linkify.addLinks(s, Linkify.ALL); diff --git a/app/src/main/res/xml/network_datasource_prefs.xml b/app/src/main/res/xml/network_datasource_prefs.xml index 5b48af2..9ccc76a 100644 --- a/app/src/main/res/xml/network_datasource_prefs.xml +++ b/app/src/main/res/xml/network_datasource_prefs.xml @@ -12,15 +12,15 @@ android:summary="Period between server data requests in miliseconds." android:title="Data Update Period (ms)" /> + android:title="Connection Timeout Period (ms)" /> + android:title="Read Timeout Period (ms)" /> \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3a4494c..2f60b76 100644 --- a/build.gradle +++ b/build.gradle @@ -2,14 +2,22 @@ buildscript { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'com.android.tools.build:gradle:3.2.1' } } allprojects { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } } diff --git a/doc/Android App Structure.odp b/doc/Android App Structure.odp new file mode 100644 index 0000000..d9b19b9 Binary files /dev/null and b/doc/Android App Structure.odp differ diff --git a/doc/Android App Structure.pdf b/doc/Android App Structure.pdf new file mode 100644 index 0000000..9863f64 Binary files /dev/null and b/doc/Android App Structure.pdf differ diff --git a/doc/Developer_Guide.txt b/doc/Developer_Guide.txt new file mode 100644 index 0000000..97296a5 --- /dev/null +++ b/doc/Developer_Guide.txt @@ -0,0 +1,62 @@ +OpenSeizureDetector Developer Guide (for V3.0 and higher) + +The OpenSeizureDetector main app is the alarm system. It monitors one +or more data sources which send it seizure detector data using broadcast +itents. If alarm conditions are experienced it will raise audible alarms +and SMS alarms if configured in the settings. +If seizure detector data is not received at the expected time, it will raise +fault alarms to warn the user of a problem. + +The OpenSeizureDetector StartUpActivity does the following: +- Start the SdServer background service that does the seizure detector + monitoring. +- Monitors SdServer for a number of conditions to be met, which shows that it + is running correctly. +- Once it is running correctly, StartUpActivity exits, and MainActivity starts + to provide user display of seizure detector data. + +The MainActivity does the following: +- Monitor the status of the SdServer background service, and display data + relating to the server on the screen for the user. +- Provide user interface to cancel audible alarms, accept alarms, and + open settings editing screens to configure OpenSeizureDetector. + +The SdServer background service does the following. +- Reads configuration data from local stored preferences, including which + data sources are to be used. +- Sends a broadcast intent to the required data sources asking them to start. +- Monitors for broadcast intents from the data sources which contain seizure + detector data. +- Checks the time since the last data was received from the data source, and + if it is longer than a specified period, attempts to re-start the data + source. If data is still not received, raises a system fault alarm. +- Checks the seizure detector data received from the data source, and raises + audible and SMS alarms if an alarm state is detected. +- Provieds a web interface to allow users to monitor the seizure detector + status using a web browser or other http client. + + +Indidual Data Source apps are separate .apk packages. They provide: +- A broadcast receiver that will receive start/stop requests from the + main OpenSeizureDetector SdServer process. +- A background SdDataSourceService service that interfaces with the seizure + detector hardware (e.g. a smart watch) and receives data from the hardware. + It carries out the necessary processing to determine if an alarm condition + is present, and sends a broadcast intent to the OpenSeizureDetector SdServer + service with the data when it has been processed. +- A configuration user interface to allow the data source to be configured. + + +Version V3.0 will initially provide two data sources that will reproduce the +functionality of V2.5.x: +- SdDataSourcePebble - pebble watch data source +- SdDataSourceNetwork - actively request data from the web interface of another + OpenSeizureDetector instance. +These will be packages uk.org.openseizuredetector.datasource.pebble and +uk.org.openseizuredetector.datasource.network + +Future data sources will be: +- SdDataSourceGarmin - uses a Garmin ConnectIQ smart watch. +- SdDataSourceAndroidWear - Uses an Android Wear smart watch. +- SdDataSourceAudio - uses the microphone on the phone to detect abnormal sounds. + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 76226d3..d791226 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Dec 03 09:39:36 GMT 2017 +#Wed Dec 26 18:31:40 GMT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip