├── shareddata
├── .gitignore
├── libs
│ └── commons-math3-3.6.jar
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── pimpimmobile
│ │ │ └── librealarm
│ │ │ └── shareddata
│ │ │ ├── PredictionData.java
│ │ │ ├── GlucoseData.java
│ │ │ ├── ReadingData.java
│ │ │ ├── Status.java
│ │ │ ├── AlertRules.java
│ │ │ ├── WearableApi.java
│ │ │ ├── AlgorithmUtil.java
│ │ │ └── PreferencesUtil.java
│ │ └── res
│ │ └── values
│ │ └── base-strings.xml
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── Application
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable-hdpi
│ │ │ ├── tile.9.png
│ │ │ ├── ic_drawer.png
│ │ │ ├── ic_content_picture.png
│ │ │ ├── ic_arrow_upward_white_24dp.png
│ │ │ ├── ic_arrow_downward_white_24dp.png
│ │ │ ├── ic_arrow_forward_white_24dp.png
│ │ │ ├── ic_arrow_slight_down_white_24dp.png
│ │ │ └── ic_arrow_slight_up_white_24dp.png
│ │ ├── drawable-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_content_picture.png
│ │ │ ├── ic_arrow_upward_white_24dp.png
│ │ │ ├── ic_arrow_downward_white_24dp.png
│ │ │ ├── ic_arrow_forward_white_24dp.png
│ │ │ ├── ic_arrow_slight_up_white_24dp.png
│ │ │ └── ic_arrow_slight_down_white_24dp.png
│ │ ├── drawable-mdpi
│ │ │ ├── ic_content_picture.png
│ │ │ ├── ic_arrow_upward_white_24dp.png
│ │ │ ├── ic_arrow_downward_white_24dp.png
│ │ │ ├── ic_arrow_forward_white_24dp.png
│ │ │ ├── ic_arrow_slight_down_white_24dp.png
│ │ │ └── ic_arrow_slight_up_white_24dp.png
│ │ ├── drawable-xhdpi
│ │ │ ├── ic_content_picture.png
│ │ │ ├── ic_arrow_forward_white_24dp.png
│ │ │ ├── ic_arrow_upward_white_24dp.png
│ │ │ ├── ic_arrow_downward_white_24dp.png
│ │ │ ├── ic_arrow_slight_up_white_24dp.png
│ │ │ └── ic_arrow_slight_down_white_24dp.png
│ │ ├── values
│ │ │ ├── dimens.xml
│ │ │ ├── attrs.xml
│ │ │ ├── integers.xml
│ │ │ ├── base-strings.xml
│ │ │ └── strings.xml
│ │ ├── xml
│ │ │ ├── xdrip_plus_preferences.xml
│ │ │ ├── nightscout_preferences.xml
│ │ │ └── preferences.xml
│ │ ├── menu
│ │ │ └── menu.xml
│ │ ├── drawable
│ │ │ └── divider.xml
│ │ ├── layout
│ │ │ ├── main_activity.xml
│ │ │ ├── quick_settings_edit_text.xml
│ │ │ ├── alarm_dialog_layout.xml
│ │ │ ├── quick_settings_snooze_edit_text.xml
│ │ │ ├── history_item.xml
│ │ │ └── main_content.xml
│ │ ├── values-zh
│ │ │ └── strings.xml
│ │ ├── values-sv
│ │ │ └── strings.xml
│ │ └── values-es
│ │ │ └── strings.xml
│ │ ├── java
│ │ └── com
│ │ │ └── pimpimmobile
│ │ │ └── librealarm
│ │ │ ├── quicksettings
│ │ │ ├── QuickSettingsInterface.java
│ │ │ ├── QuickSettingsItem.java
│ │ │ ├── QuickSettingsView.java
│ │ │ ├── GlucoseLevelView.java
│ │ │ └── SnoozeAlarmView.java
│ │ │ ├── BootCompletedReceiver.java
│ │ │ ├── nightscout
│ │ │ ├── NightscoutPreferences.java
│ │ │ └── NightscoutUploader.java
│ │ │ ├── xdrip_plus
│ │ │ ├── XdripPlusBroadcast.java
│ │ │ └── XdripPlusPreferences.java
│ │ │ ├── libreAlarm.java
│ │ │ ├── AlarmReceiver.java
│ │ │ ├── Preferences.java
│ │ │ ├── AlarmDialogFragment.java
│ │ │ ├── HistoryAdapter.java
│ │ │ └── JoH.java
│ │ └── AndroidManifest.xml
└── build.gradle
├── Wearable
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ └── strings.xml
│ │ └── layout
│ │ │ └── wear_activity.xml
│ │ ├── java
│ │ └── com
│ │ │ └── pimpimmobile
│ │ │ └── librealarm
│ │ │ ├── AlarmIntentService.java
│ │ │ ├── libreAlarm.java
│ │ │ ├── SimpleDatabase.java
│ │ │ ├── AlarmReceiver.java
│ │ │ ├── JoH.java
│ │ │ ├── DataLayerListenerService.java
│ │ │ ├── WearIntentService.java
│ │ │ └── RootTools.java
│ │ └── AndroidManifest.xml
└── build.gradle
├── README.md
├── .gitignore
├── gradlew.bat
└── gradlew
/shareddata/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':Application', ':Wearable', ':shareddata'
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamorham/LibreAlarm/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/shareddata/libs/commons-math3-3.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamorham/LibreAlarm/HEAD/shareddata/libs/commons-math3-3.6.jar
--------------------------------------------------------------------------------
/Application/src/main/res/drawable-hdpi/tile.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamorham/LibreAlarm/HEAD/Application/src/main/res/drawable-hdpi/tile.9.png
--------------------------------------------------------------------------------
/Application/src/main/res/drawable-hdpi/ic_drawer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamorham/LibreAlarm/HEAD/Application/src/main/res/drawable-hdpi/ic_drawer.png
--------------------------------------------------------------------------------
/Application/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamorham/LibreAlarm/HEAD/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Wearable/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 | * TODO: Customize class - update intent actions, extra parameters and static
23 | * helper methods.
24 | */
25 | public class WearIntentService extends IntentService implements GoogleApiClient.ConnectionCallbacks {
26 |
27 | private static final String TAG = "LibreIntent";
28 |
29 | // TODO: Rename actions, choose action names that describe tasks that this
30 | // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
31 | private static final String ACTION_FOO = "com.pimpimmobile.librealarm.action.FOO";
32 | private static final String ACTION_BAZ = "com.pimpimmobile.librealarm.action.BAZ";
33 |
34 | // TODO: Rename parameters
35 | private static final String EXTRA_PARAM1 = "com.pimpimmobile.librealarm.extra.PARAM1";
36 | private static final String EXTRA_PARAM2 = "com.pimpimmobile.librealarm.extra.PARAM2";
37 |
38 | public static GoogleApiClient mGoogleApiClient;
39 | private static MessageApi.MessageListener remoteListener;
40 |
41 | public WearIntentService() {
42 | super("WearIntentService");
43 | }
44 |
45 | /**
46 | * Starts this service to perform action Foo with the given parameters. If
47 | * the service is already performing a task this action will be queued.
48 | *
49 | * @see IntentService
50 | */
51 | // TODO: Customize helper method
52 | public static void startActionFoo(Context context, String param1, String param2) {
53 | Intent intent = new Intent(context, WearIntentService.class);
54 | intent.setAction(ACTION_FOO);
55 | intent.putExtra(EXTRA_PARAM1, param1);
56 | intent.putExtra(EXTRA_PARAM2, param2);
57 | context.startService(intent);
58 | }
59 |
60 | public static void startActionDefault(Context context) {
61 | Intent intent = new Intent(context, WearIntentService.class);
62 | context.startService(intent);
63 | }
64 |
65 | /**
66 | * Starts this service to perform action Baz with the given parameters. If
67 | * the service is already performing a task this action will be queued.
68 | *
69 | * @see IntentService
70 | */
71 | // TODO: Customize helper method
72 | public static void startActionBaz(Context context, String param1, String param2) {
73 | Intent intent = new Intent(context, WearIntentService.class);
74 | intent.setAction(ACTION_BAZ);
75 | intent.putExtra(EXTRA_PARAM1, param1);
76 | intent.putExtra(EXTRA_PARAM2, param2);
77 | context.startService(intent);
78 | }
79 |
80 | @Override
81 | protected void onHandleIntent(Intent intent) {
82 | final PowerManager.WakeLock wl = JoH.getWakeLock(this, "intent-service", 30000);
83 | Log.e(TAG, "IntentService Triggered!");
84 | try {
85 | if (intent != null) {
86 | final String action = intent.getAction();
87 | if (ACTION_FOO.equals(action)) {
88 | final String param1 = intent.getStringExtra(EXTRA_PARAM1);
89 | final String param2 = intent.getStringExtra(EXTRA_PARAM2);
90 | handleActionFoo(param1, param2);
91 | } else if (ACTION_BAZ.equals(action)) {
92 | final String param1 = intent.getStringExtra(EXTRA_PARAM1);
93 | final String param2 = intent.getStringExtra(EXTRA_PARAM2);
94 | handleActionBaz(param1, param2);
95 | }
96 | }
97 |
98 |
99 | if (libreAlarm.noNFC()) {
100 | Log.e(TAG, "Device has no NFC! - not doing anything");
101 | } else {
102 |
103 | reconnectGoogle();
104 |
105 | if (PreferencesUtil.shouldUseRoot(this)) {
106 | Log.d(TAG, "Using ROOT options!");
107 | RootTools.executeScripts(true); // turn it on
108 | } else {
109 | Log.d(TAG, "Not using root options");
110 | }
111 | final NfcManager nfcManager =
112 | (NfcManager) this.getSystemService(Context.NFC_SERVICE);
113 | NfcAdapter mNfcAdapter = nfcManager.getDefaultAdapter(); // could be static?
114 | // mNfcAdapter.disableForegroundDispatch(this);
115 | if (mNfcAdapter != null) {
116 | Log.d(TAG, "Got NFC adpater - intent service");
117 | int counter = 0;
118 | try {
119 | // null pointer can trigger here from the systemapi
120 | while (((!mNfcAdapter.isEnabled() || (!mGoogleApiClient.isConnected())) && counter < 9)) {
121 | Log.d(TAG, "intent service nfc turned on (" + mNfcAdapter.isEnabled() + ") wait: " + counter + " google: " + mGoogleApiClient.isConnected());
122 | try {
123 | // quick and very dirty
124 | Thread.sleep(1000);
125 | } catch (Exception e) {
126 | //
127 | }
128 | counter++;
129 | }
130 |
131 | } catch (NullPointerException e) {
132 | Log.wtf(TAG, "Null pointer exception from NFC subsystem: " + e.toString());
133 | // TODO do we actually need to reboot watch here after some counter of failures without resolution?
134 | }
135 | } else {
136 | Log.e(TAG, "nfcAdapter is NULL!!");
137 | }
138 |
139 | // fire up the activity
140 | final Intent i = new Intent(this, WearActivity.class);
141 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
142 | startActivity(i);
143 | }
144 | } finally {
145 | JoH.releaseWakeLock(wl);
146 | }
147 | }
148 |
149 | /**
150 | * Handle action Foo in the provided background thread with the provided
151 | * parameters.
152 | */
153 | private void handleActionFoo(String param1, String param2) {
154 | // TODO: Handle action Foo
155 | throw new UnsupportedOperationException("Not yet implemented");
156 | }
157 |
158 | /**
159 | * Handle action Baz in the provided background thread with the provided
160 | * parameters.
161 | */
162 | private void handleActionBaz(String param1, String param2) {
163 | // TODO: Handle action Baz
164 | throw new UnsupportedOperationException("Not yet implemented");
165 | }
166 |
167 | private void reconnectGoogle() {
168 | Log.d(TAG, "Reconnect google called");
169 | if ((mGoogleApiClient == null) || (!mGoogleApiClient.isConnected())) {
170 | Log.d(TAG, "Attempting to connect to google api");
171 | mGoogleApiClient = new GoogleApiClient.Builder(this)
172 | .addApi(Wearable.API)
173 | .addConnectionCallbacks(this)
174 | // .addOnConnectionFailedListener(this)
175 | .build();
176 |
177 | mGoogleApiClient.connect();
178 |
179 | } else {
180 | Log.d(TAG, "Already connected google api");
181 | onConnected(null);
182 | }
183 | }
184 |
185 | @Override
186 | public void onConnected(Bundle connectionHint) {
187 | Log.i(TAG, "google api is connected!! - not adding listener yet or sending status update!?");
188 | //Wearable.MessageApi.addListener(mGoogleApiClient, this);
189 | //sendStatusUpdate(Status.Type.ATTEMPTING);
190 | }
191 |
192 | @Override
193 | public void onConnectionSuspended(int cause) {
194 | Log.d(TAG, "onConnectionSuspended(): Connection to Google API client was suspended");
195 | }
196 |
197 | public synchronized static void tryToAddListener(MessageApi.MessageListener listener) {
198 | // TODO check nulls
199 | if (mGoogleApiClient.isConnected()) {
200 | removeExistingListener();
201 | Log.d(TAG, "Adding remote listener!");
202 | Wearable.MessageApi.addListener(mGoogleApiClient, listener);
203 | } else {
204 | Log.e(TAG, "Can't add listener as we are not connected!");
205 | }
206 | }
207 |
208 | public synchronized static void tryToRemoveListener(MessageApi.MessageListener listener) {
209 | // TODO check nulls - check if we should remove even if not connected
210 | // if (mGoogleApiClient.isConnected()) {
211 | if (mGoogleApiClient != null) {
212 | try {
213 | removeExistingListener();
214 | } catch (Exception e) {
215 | Log.e(TAG, "Got exception removing remote listener: " + e);
216 | }
217 | try {
218 | Wearable.MessageApi.removeListener(mGoogleApiClient, listener);
219 | } catch (Exception e) {
220 | Log.e(TAG, "Got exception removing listener: " + e);
221 | }
222 | }
223 | }
224 |
225 | private static void removeExistingListener() {
226 | if (remoteListener != null) {
227 | Log.e(TAG, "First removing remote listener!");
228 | Wearable.MessageApi.removeListener(mGoogleApiClient, remoteListener);
229 | remoteListener = null;
230 | }
231 | }
232 |
233 | }
234 |
--------------------------------------------------------------------------------
/shareddata/src/main/java/com/pimpimmobile/librealarm/shareddata/PreferencesUtil.java:
--------------------------------------------------------------------------------
1 | package com.pimpimmobile.librealarm.shareddata;
2 |
3 | import android.content.Context;
4 | import android.preference.PreferenceManager;
5 | import android.util.Log;
6 |
7 | import com.google.gson.JsonObject;
8 |
9 | import org.json.JSONException;
10 | import org.json.JSONObject;
11 |
12 | import java.util.HashMap;
13 | import java.util.Iterator;
14 |
15 | public class PreferencesUtil {
16 |
17 | public static final String TRUE_MARKER = "___TRUE___";
18 | public static final String FALSE_MARKER = "___FALSE___";
19 |
20 | private static final String TAG = "LibrePrefUtil";
21 |
22 | public static int battery_threshold = -1;
23 |
24 | // Used on phone
25 | public static Boolean isNsRestEnabled(Context context) {
26 | return getBoolean(context, "ns_rest");
27 | }
28 |
29 | // Used on phone
30 | public static Boolean isXdripPlusEnabled(Context context) {
31 | return getBoolean(context, "xdrip_plus_broadcast");
32 | }
33 |
34 | public static String getNsRestUrl(Context context) {
35 | return getString(context, "ns_rest_uri");
36 | }
37 | // End used on phone
38 |
39 | // Used on watch
40 | public static void setIsStarted(Context context, boolean started) {
41 | setBoolean(context, "startstopflag", started);
42 | }
43 |
44 | public static boolean getIsStarted(Context context) {
45 | return getBoolean(context, "startstopflag");
46 | }
47 |
48 | // Used on phone
49 | public static void setIsStartedPhone(Context context, boolean started) {
50 | setBoolean(context, "phone-startstopflag", started);
51 | }
52 |
53 | public static boolean getIsStartedPhone(Context context) {
54 | return getBoolean(context, "phone-startstopflag", true);
55 | }
56 |
57 | public static void setRetries(Context context, int attempts) {
58 | setInt(context, "retries", attempts);
59 | }
60 |
61 | public static int getRetries(Context context) {
62 | return getInt(context, "retries", 1);
63 | }
64 |
65 | public static long getLastBoot(Context context) {
66 | return getLong(context, "last_boot");
67 | }
68 |
69 | public static void setLastBoot(Context context, long time) {
70 | setLong(context, "last_boot", time);
71 | }
72 |
73 | public static Status.Type getCurrentType(Context context) {
74 | return Status.Type.values()[getInt(context, "current_type", Status.Type.NOT_RUNNING.ordinal())];
75 | }
76 |
77 | public static void setCurrentType(Context context, Status.Type type) {
78 | setInt(context, "current_type", type.ordinal());
79 | }
80 |
81 | public static long errInRowForAlarm(Context context) {
82 | if ("true".equals(getString(context, context.getString(R.string.pref_key_err_alarm_enabled), "false"))) {
83 | return Long.valueOf(getString(context, context.getString(R.string.pref_key_err_alarm), "2"));
84 | }
85 | return Long.MAX_VALUE;
86 | }
87 |
88 | public static int increaseErrorsInARow(Context context) {
89 | int errorsInRow = getInt(context, "errors_in_a_row", 0) + 1;
90 | setInt(context, "errors_in_a_row", errorsInRow);
91 | return errorsInRow;
92 | }
93 |
94 | public static void resetErrorsInARow(Context context) {
95 | setInt(context, "errors_in_a_row", 0);
96 | }
97 |
98 | public static Boolean slowCpu(Context context) {
99 | return getBoolean(context, context.getString(R.string.pref_key_clock_speed), false);
100 | }
101 |
102 | public static Boolean disableTouchscreen(Context context) {
103 | return getBoolean(context, context.getString(R.string.pref_key_disable_touchscreen), false);
104 | }
105 |
106 | public static Boolean toggleNFC(Context context) {
107 | return getBoolean(context, context.getString(R.string.pref_key_switch_nfc), false);
108 | }
109 |
110 | public static Boolean toggleNFConError(Context context) {
111 | return getBoolean(context, context.getString(R.string.pref_key_switch_nfc_on_error), true);
112 | }
113 |
114 | public static Boolean automaticallyEnableTheatreMode(Context context) {
115 | return getBoolean(context, context.getString(R.string.pref_key_auto_theatre_mode), false);
116 | }
117 |
118 | public static Boolean useHalfSpeed(Context context) {
119 | return getBoolean(context, context.getString(R.string.pref_key_auto_half_speed), false);
120 | }
121 |
122 | public static Boolean uninstallxDrip(Context context) {
123 | return getBoolean(context, context.getString(R.string.pref_key_uninstall_xdrip), false);
124 | }
125 |
126 | public static String getCheckGlucoseInterval(Context context) {
127 | return getString(context, context.getString(R.string.pref_key_glucose_interval), "5");
128 | }
129 |
130 | public static String getHalfThreshold(Context context) {
131 | return getString(context, context.getString(R.string.pref_key_half_percent), "30");
132 | }
133 |
134 | public static int getHalfThresholdNumber(Context context) {
135 | final String val = getHalfThreshold(context);
136 | try {
137 | final int value = Integer.parseInt(val);
138 | if (value < 2 || value > 90) return 30;
139 | return value;
140 | } catch (Exception e) {
141 | return 30;
142 | }
143 | }
144 |
145 | public static void updateBatteryThresholdCache(Context context) {
146 | battery_threshold = getHalfThresholdNumber(context);
147 | }
148 |
149 | public static Boolean shouldUseRoot(Context context) {
150 | return getBoolean(context, context.getString(R.string.pref_key_root));
151 | }
152 |
153 | public static boolean shouldGoHalfSpeed(Context context, int battery_level) {
154 | if (battery_threshold < 1) {
155 | battery_threshold = getHalfThresholdNumber(context);
156 | }
157 | if ((battery_level < 1) || (battery_level > battery_threshold)) {
158 | return false;
159 | } else {
160 | return useHalfSpeed(context);
161 | }
162 | }
163 |
164 | /// / End used in watch
165 |
166 | public static void setBoolean(Context context, String key, boolean value) {
167 | PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply();
168 | }
169 |
170 | public static boolean getBoolean(Context context, String key) {
171 | return getBoolean(context, key, false);
172 | }
173 |
174 | public static boolean getBoolean(Context context, String key, boolean default_) {
175 | // booleans get stored on watch as strings due to the way data is synced
176 | try {
177 | return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(key, default_);
178 | } catch (ClassCastException e) {
179 | return PreferencesUtil.getString(context, key).equals("true");
180 | }
181 | }
182 |
183 | public static void setInt(Context context, String key, int value) {
184 | PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(key, value).apply();
185 | }
186 |
187 | public static int getInt(Context context, int id) {
188 | return getInt(context, context.getString(id), -1);
189 | }
190 |
191 | public static int getInt(Context context, String key, int default_) {
192 | return PreferenceManager.getDefaultSharedPreferences(context).getInt(key, default_);
193 | }
194 |
195 | public static void setLong(Context context, String key, long value) {
196 | PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(key, value).apply();
197 | }
198 |
199 | public static long getLong(Context context, int id) {
200 | return getLong(context, context.getString(id));
201 | }
202 |
203 | public static long getLong(Context context, String key) {
204 | return PreferenceManager.getDefaultSharedPreferences(context).getLong(key, -1);
205 | }
206 |
207 | public static String getString(Context context, int id) {
208 | return getString(context, context.getString(id));
209 | }
210 |
211 | public static String getString(Context context, String key) {
212 | return getString(context, key, "-1");
213 | }
214 |
215 | public static String getString(Context context, int keyId, String default_) {
216 | return PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(keyId), default_);
217 | }
218 |
219 | public static String getString(Context context, String key, String default_) {
220 | return PreferenceManager.getDefaultSharedPreferences(context).getString(key, default_);
221 | }
222 |
223 | public static void putString(Context context, String key, String value) {
224 | PreferenceManager.getDefaultSharedPreferences(context).edit().putString(key, value).apply();
225 | }
226 |
227 | public static void putBoolean(Context context, String key, boolean value) {
228 | PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply();
229 | }
230 |
231 | public static float getFloat(Context context, int id) {
232 | return getFloat(context, context.getString(id));
233 | }
234 |
235 | public static float getFloat(Context context, String key) {
236 | return PreferenceManager.getDefaultSharedPreferences(context).getFloat(key, -1);
237 | }
238 |
239 | public static String toString(HashMap