Merge branch 'dev' into dagger3

This commit is contained in:
Milos Kozak 2020-03-10 22:39:26 +01:00
commit 99aec40534
13 changed files with 319 additions and 255 deletions

View file

@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="com.dexcom.cgm.EXTERNAL_PERMISSION" /> <uses-permission android:name="com.dexcom.cgm.EXTERNAL_PERMISSION" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -123,14 +124,6 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- Network change local receiver -->
<receiver android:name=".receivers.NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider" android:authorities="${applicationId}.fileprovider"
@ -264,6 +257,8 @@
<activity <activity
android:name=".plugins.pump.insight.activities.InsightAlertActivity" android:name=".plugins.pump.insight.activities.InsightAlertActivity"
android:label="@string/pump_alert" android:label="@string/pump_alert"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:theme="@style/InsightAlertDialog" /> android:theme="@style/InsightAlertDialog" />
<activity <activity
android:name=".plugins.pump.insight.activities.InsightPairingInformationActivity" android:name=".plugins.pump.insight.activities.InsightPairingInformationActivity"

View file

@ -7,6 +7,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import androidx.annotation.ColorRes; import androidx.annotation.ColorRes;
import androidx.annotation.PluralsRes; import androidx.annotation.PluralsRes;
@ -102,6 +104,7 @@ import info.nightscout.androidaps.plugins.source.XdripPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver; import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver; import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver;
import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.ActivityMonitor; import info.nightscout.androidaps.utils.ActivityMonitor;
@ -357,6 +360,11 @@ public class MainApp extends DaggerApplication {
this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver(); this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver();
this.timeDateOrTZChangeReceiver.registerBroadcasts(this); this.timeDateOrTZChangeReceiver.registerBroadcasts(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION );
registerReceiver(new NetworkChangeReceiver(), intentFilter);
} }
@Deprecated @Deprecated

View file

@ -3,9 +3,7 @@ package info.nightscout.androidaps.plugins.pump.common.bolusInfo
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.logging.L import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper import info.nightscout.androidaps.logging.StacktraceLoggerWrapper
import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import org.slf4j.LoggerFactory
import java.util.* import java.util.*
import kotlin.math.abs import kotlin.math.abs
@ -21,10 +19,6 @@ object DetailedBolusInfoStorage {
@Synchronized @Synchronized
fun findDetailedBolusInfo(bolusTime: Long, bolus: Double): DetailedBolusInfo? { fun findDetailedBolusInfo(bolusTime: Long, bolus: Double): DetailedBolusInfo? {
if (MedtronicHistoryData.doubleBolusDebug)
log.debug("DoubleBolusDebug: findDetailedBolusInfo::bolusTime={}, bolus={}", bolusTime, bolus)
// Look for info with bolus // Look for info with bolus
for (i in store.indices) { for (i in store.indices) {
val d = store[i] val d = store[i]
@ -32,11 +26,8 @@ object DetailedBolusInfoStorage {
log.debug("Existing bolus info: " + store[i]) log.debug("Existing bolus info: " + store[i])
if (bolusTime > d.date - T.mins(1).msecs() && bolusTime < d.date + T.mins(1).msecs() && abs(store[i].insulin - bolus) < 0.01) { if (bolusTime > d.date - T.mins(1).msecs() && bolusTime < d.date + T.mins(1).msecs() && abs(store[i].insulin - bolus) < 0.01) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Using & removing bolus info: " + store[i]) log.debug("Using & removing bolus info: ${store[i]}")
store.removeAt(i) store.removeAt(i)
if (MedtronicHistoryData.doubleBolusDebug)
log.debug("DoubleBolusDebug: findDetailedBolusInfo::selectedBolus[DetailedBolusInfo={}]", d)
return d return d
} }
} }
@ -45,13 +36,24 @@ object DetailedBolusInfoStorage {
val d = store[i] val d = store[i]
if (bolusTime > d.date - T.mins(1).msecs() && bolusTime < d.date + T.mins(1).msecs() && bolus <= store[i].insulin + 0.01) { if (bolusTime > d.date - T.mins(1).msecs() && bolusTime < d.date + T.mins(1).msecs() && bolus <= store[i].insulin + 0.01) {
if (L.isEnabled(L.PUMP)) if (L.isEnabled(L.PUMP))
log.debug("Using & removing bolus info: " + store[i]) log.debug("Using TIME-ONLY & removing bolus info: ${store[i]}")
store.removeAt(i) store.removeAt(i)
if (MedtronicHistoryData.doubleBolusDebug)
log.debug("DoubleBolusDebug: findDetailedBolusInfo::selectedBolus[DetailedBolusInfo={}]", d)
return d return d
} }
} }
// If not found, use last record if amount is the same
if (store.size > 0) {
val d = store[store.size - 1]
if (abs(d.insulin - bolus) < 0.01) {
if (L.isEnabled(L.PUMP))
log.debug("Using LAST & removing bolus info: $d")
store.removeAt(store.size - 1)
return d
}
}
//Not found
if (L.isEnabled(L.PUMP))
log.debug("Bolus info not found")
return null return null
} }
} }

View file

@ -11,7 +11,7 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage.findDetailedBolusInfo import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
@ -107,7 +107,7 @@ open class DanaRS_Packet_APS_History_Events(
} }
DanaRPump.BOLUS -> { DanaRPump.BOLUS -> {
val detailedBolusInfo = findDetailedBolusInfo(datetime, param1 / 100.0) val detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo() ?: DetailedBolusInfo()
detailedBolusInfo.date = datetime detailedBolusInfo.date = datetime
detailedBolusInfo.source = Source.PUMP detailedBolusInfo.source = Source.PUMP
@ -119,7 +119,7 @@ open class DanaRS_Packet_APS_History_Events(
} }
DanaRPump.DUALBOLUS -> { DanaRPump.DUALBOLUS -> {
val detailedBolusInfo = findDetailedBolusInfo(datetime, param1 / 100.0) val detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime, param1 / 100.0)
?: DetailedBolusInfo() ?: DetailedBolusInfo()
detailedBolusInfo.date = datetime detailedBolusInfo.date = datetime
detailedBolusInfo.source = Source.PUMP detailedBolusInfo.source = Source.PUMP

View file

@ -1,25 +1,25 @@
package info.nightscout.androidaps.plugins.pump.insight; package info.nightscout.androidaps.plugins.pump.insight;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper;
import android.os.Vibrator; import android.os.Vibrator;
import android.text.Html;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.lifecycle.MutableLiveData;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertActivity; import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertActivity;
@ -33,19 +33,20 @@ import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState; import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState;
import info.nightscout.androidaps.plugins.pump.insight.exceptions.InsightException; import info.nightscout.androidaps.plugins.pump.insight.exceptions.InsightException;
import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AppLayerErrorException; import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AppLayerErrorException;
import info.nightscout.androidaps.plugins.pump.insight.utils.AlertUtilsKt;
import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator; import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator;
public class InsightAlertService extends Service implements InsightConnectionService.StateCallback { public class InsightAlertService extends Service implements InsightConnectionService.StateCallback {
private static Logger log = StacktraceLoggerWrapper.getLogger(L.PUMPCOMM); private static Logger log = StacktraceLoggerWrapper.getLogger(L.PUMPCOMM);
private static final int NOTIFICATION_ID = 31345;
private LocalBinder localBinder = new LocalBinder(); private LocalBinder localBinder = new LocalBinder();
private boolean connectionRequested; private boolean connectionRequested;
private final Object $alertLock = new Object[0]; private final Object $alertLock = new Object[0];
private Alert alert; private Alert alert = null;
private MutableLiveData<Alert> alertLiveData = new MutableLiveData<>();
private Thread thread; private Thread thread;
private InsightAlertActivity alertActivity;
private Ringtone ringtone;
private Vibrator vibrator; private Vibrator vibrator;
private boolean vibrating; private boolean vibrating;
private InsightConnectionService connectionService; private InsightConnectionService connectionService;
@ -66,27 +67,6 @@ public class InsightAlertService extends Service implements InsightConnectionSer
} }
}; };
private void retrieveRingtone() {
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
ringtone = RingtoneManager.getRingtone(this, uri);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ringtone.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setLegacyStreamType(AudioManager.STREAM_RING).build());
} else ringtone.setStreamType(AudioManager.STREAM_RING);
}
public Alert getAlert() {
synchronized ($alertLock) {
return alert;
}
}
public void setAlertActivity(InsightAlertActivity alertActivity) {
this.alertActivity = alertActivity;
}
public void ignore(AlertType alertType) { public void ignore(AlertType alertType) {
synchronized ($alertLock) { synchronized ($alertLock) {
if (alertType == null) { if (alertType == null) {
@ -99,6 +79,10 @@ public class InsightAlertService extends Service implements InsightConnectionSer
} }
} }
public MutableLiveData<Alert> getAlertLiveData() {
return alertLiveData;
}
@Nullable @Nullable
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
@ -109,6 +93,7 @@ public class InsightAlertService extends Service implements InsightConnectionSer
public void onCreate() { public void onCreate() {
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE); bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
alertLiveData.setValue(null);
} }
@Override @Override
@ -119,6 +104,12 @@ public class InsightAlertService extends Service implements InsightConnectionSer
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if ("mute".equals(intent.getStringExtra("command"))) {
mute();
} else if ("confirm".equals(intent.getStringExtra("command"))) {
dismissNotification();
confirm();
}
return START_STICKY; return START_STICKY;
} }
@ -128,25 +119,47 @@ public class InsightAlertService extends Service implements InsightConnectionSer
thread = new Thread(this::queryActiveAlert); thread = new Thread(this::queryActiveAlert);
thread.start(); thread.start();
} else if (thread != null) thread.interrupt(); } else {
dismissNotification();
if (thread != null) thread.interrupt();
}
} }
private void queryActiveAlert() { private void queryActiveAlert() {
while (!Thread.currentThread().isInterrupted()) { while (!Thread.currentThread().isInterrupted()) {
try { try {
Alert alert = connectionService.requestMessage(new GetActiveAlertMessage()).await().getAlert();
if (Thread.currentThread().isInterrupted()) {
connectionService.withdrawConnectionRequest(thread);
break;
}
synchronized ($alertLock) { synchronized ($alertLock) {
if ((this.alert == null && alert != null) Alert alert = connectionService.requestMessage(new GetActiveAlertMessage()).await().getAlert();
if (alert == null || (alert.getAlertType() == ignoreType && System.currentTimeMillis() - ignoreTimestamp < 10000)) {
if (connectionRequested) {
connectionService.withdrawConnectionRequest(this);
connectionRequested = false;
}
this.alertLiveData.postValue(null);
this.alert = null;
dismissNotification();
stopAlerting();
} else if (!alert.equals(this.alert)) {
if (!connectionRequested) {
connectionService.requestConnection(this);
connectionRequested = true;
}
showNotification(alert);
this.alertLiveData.postValue(alert);
this.alert = alert;
if (alert.getAlertStatus() == AlertStatus.SNOOZED) stopAlerting();
else alert();
}
/*if ((this.alert == null && alert != null)
|| (this.alert != null && alert == null) || (this.alert != null && alert == null)
|| (this.alert != null && alert != null && !this.alert.equals(alert))) { || (this.alert != null && alert != null && !this.alert.equals(alert))) {
if (this.alert != null && (alert == null || this.alert.getAlertId() != alert.getAlertId())) stopAlerting(); if (this.alert != null && (alert == null || this.alert.getAlertId() != alert.getAlertId())) stopAlerting();
this.alert = alert; this.alert = alert;
if (alertActivity != null && alert != null) if (alert != null)
new Handler(Looper.getMainLooper()).post(() -> alertActivity.update(alert)); new Handler(Looper.getMainLooper()).post(() -> {
//showNotification(alert);
//alertActivity.update(alert);
});
} }
if (alert == null) { if (alert == null) {
stopAlerting(); stopAlerting();
@ -154,8 +167,10 @@ public class InsightAlertService extends Service implements InsightConnectionSer
connectionService.withdrawConnectionRequest(this); connectionService.withdrawConnectionRequest(this);
connectionRequested = false; connectionRequested = false;
} }
if (alertActivity != null) new Handler(Looper.getMainLooper()).post(() -> {
new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish()); //dismissNotification();
//alertActivity.finish();
});
} else if (!(alert.getAlertType() == ignoreType && System.currentTimeMillis() - ignoreTimestamp < 10000)) { } else if (!(alert.getAlertType() == ignoreType && System.currentTimeMillis() - ignoreTimestamp < 10000)) {
if (alert.getAlertStatus() == AlertStatus.ACTIVE) alert(); if (alert.getAlertStatus() == AlertStatus.ACTIVE) alert();
else stopAlerting(); else stopAlerting();
@ -163,12 +178,12 @@ public class InsightAlertService extends Service implements InsightConnectionSer
connectionService.requestConnection(this); connectionService.requestConnection(this);
connectionRequested = true; connectionRequested = true;
} }
if (alertActivity == null) { /*if (alertActivity == null) {
Intent intent = new Intent(InsightAlertService.this, InsightAlertActivity.class); Intent intent = new Intent(InsightAlertService.this, InsightAlertActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
new Handler(Looper.getMainLooper()).post(() -> startActivity(intent)); new Handler(Looper.getMainLooper()).post(() -> startActivity(intent));
} }*/
} //}
} }
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
connectionService.withdrawConnectionRequest(thread); connectionService.withdrawConnectionRequest(thread);
@ -190,21 +205,18 @@ public class InsightAlertService extends Service implements InsightConnectionSer
connectionService.withdrawConnectionRequest(thread); connectionService.withdrawConnectionRequest(thread);
connectionRequested = false; connectionRequested = false;
} }
if (alertActivity != null)
new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish());
stopAlerting(); stopAlerting();
alertLiveData.postValue(null);
this.alert = null;
dismissNotification();
thread = null; thread = null;
} }
private void alert() { private void alert() {
if (!vibrating) { if (!vibrating) {
vibrator.vibrate(new long[] {0, 1000, 1000}, 0); vibrator.vibrate(new long[]{0, 1000, 1000}, 0);
vibrating = true; vibrating = true;
} }
if (ringtone == null || !ringtone.isPlaying()) {
retrieveRingtone();
ringtone.play();
}
} }
private void stopAlerting() { private void stopAlerting() {
@ -212,15 +224,21 @@ public class InsightAlertService extends Service implements InsightConnectionSer
vibrator.cancel(); vibrator.cancel();
vibrating = false; vibrating = false;
} }
if (ringtone != null && ringtone.isPlaying()) ringtone.stop();
} }
public void mute() { public void mute() {
new Thread(() -> { new Thread(() -> {
try { try {
SnoozeAlertMessage snoozeAlertMessage = new SnoozeAlertMessage(); synchronized ($alertLock) {
snoozeAlertMessage.setAlertID(alert.getAlertId()); if (alert == null) return;
connectionService.requestMessage(snoozeAlertMessage).await(); alert.setAlertStatus(AlertStatus.SNOOZED);
alertLiveData.postValue(alert);
stopAlerting();
showNotification(alert);
SnoozeAlertMessage snoozeAlertMessage = new SnoozeAlertMessage();
snoozeAlertMessage.setAlertID(alert.getAlertId());
connectionService.requestMessage(snoozeAlertMessage).await();
}
} catch (AppLayerErrorException e) { } catch (AppLayerErrorException e) {
log.info("Exception while muting alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); log.info("Exception while muting alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")");
ExceptionTranslator.makeToast(InsightAlertService.this, e); ExceptionTranslator.makeToast(InsightAlertService.this, e);
@ -237,9 +255,16 @@ public class InsightAlertService extends Service implements InsightConnectionSer
public void confirm() { public void confirm() {
new Thread(() -> { new Thread(() -> {
try { try {
ConfirmAlertMessage confirmAlertMessage = new ConfirmAlertMessage(); synchronized ($alertLock) {
confirmAlertMessage.setAlertID(alert.getAlertId()); if (alert == null) return;
connectionService.requestMessage(confirmAlertMessage).await(); stopAlerting();
alertLiveData.postValue(null);
dismissNotification();
ConfirmAlertMessage confirmAlertMessage = new ConfirmAlertMessage();
confirmAlertMessage.setAlertID(alert.getAlertId());
connectionService.requestMessage(confirmAlertMessage).await();
this.alert = null;
}
} catch (AppLayerErrorException e) { } catch (AppLayerErrorException e) {
log.info("Exception while confirming alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); log.info("Exception while confirming alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")");
ExceptionTranslator.makeToast(InsightAlertService.this, e); ExceptionTranslator.makeToast(InsightAlertService.this, e);
@ -253,6 +278,48 @@ public class InsightAlertService extends Service implements InsightConnectionSer
}).start(); }).start();
} }
private void showNotification(Alert alert) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, LocalInsightPlugin.ALERT_CHANNEL_ID);
notificationBuilder.setPriority(NotificationCompat.PRIORITY_MAX);
notificationBuilder.setCategory(NotificationCompat.CATEGORY_ALARM);
notificationBuilder.setVibrate(new long[0]);
notificationBuilder.setShowWhen(false);
notificationBuilder.setOngoing(true);
notificationBuilder.setOnlyAlertOnce(true);
notificationBuilder.setAutoCancel(false);
notificationBuilder.setSmallIcon(AlertUtilsKt.getAlertIcon(alert.getAlertCategory()));
notificationBuilder.setContentTitle(AlertUtilsKt.getAlertCode(alert.getAlertType()) + " " + AlertUtilsKt.getAlertTitle(alert.getAlertType()));
String description = AlertUtilsKt.getAlertDescription(alert);
if (description != null)
notificationBuilder.setContentText(Html.fromHtml(description).toString());
Intent fullScreenIntent = new Intent(this, InsightAlertActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setFullScreenIntent(fullScreenPendingIntent, true);
switch (alert.getAlertStatus()) {
case ACTIVE:
Intent muteIntent = new Intent(this, InsightAlertService.class).putExtra("command", "mute");
PendingIntent mutePendingIntent = PendingIntent.getService(this, 1, muteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.addAction(0, MainApp.gs(R.string.mute_alert), mutePendingIntent);
case SNOOZED:
Intent confirmIntent = new Intent(this, InsightAlertService.class).putExtra("command", "confirm");
PendingIntent confirmPendingIntent = PendingIntent.getService(this, 2, confirmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.addAction(0, MainApp.gs(R.string.confirm), confirmPendingIntent);
}
Notification notification = notificationBuilder.build();
NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, notification);
startForeground(NOTIFICATION_ID, notification);
}
private void dismissNotification() {
NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID);
stopForeground(true);
}
public class LocalBinder extends Binder { public class LocalBinder extends Binder {
public InsightAlertService getService() { public InsightAlertService getService() {
return InsightAlertService.this; return InsightAlertService.this;

View file

@ -1,9 +1,12 @@
package info.nightscout.androidaps.plugins.pump.insight; package info.nightscout.androidaps.plugins.pump.insight;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
@ -149,6 +152,8 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
private final SP sp; private final SP sp;
private final CommandQueueProvider commandQueue; private final CommandQueueProvider commandQueue;
public static final String ALERT_CHANNEL_ID = "AndroidAPS-InsightAlert";
private Logger log = StacktraceLoggerWrapper.getLogger(L.PUMP); private Logger log = StacktraceLoggerWrapper.getLogger(L.PUMP);
private PumpDescription pumpDescription; private PumpDescription pumpDescription;
@ -274,6 +279,16 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
super.onStart(); super.onStart();
MainApp.instance().bindService(new Intent(MainApp.instance(), InsightConnectionService.class), serviceConnection, Context.BIND_AUTO_CREATE); MainApp.instance().bindService(new Intent(MainApp.instance(), InsightConnectionService.class), serviceConnection, Context.BIND_AUTO_CREATE);
MainApp.instance().bindService(new Intent(MainApp.instance(), InsightAlertService.class), serviceConnection, Context.BIND_AUTO_CREATE); MainApp.instance().bindService(new Intent(MainApp.instance(), InsightAlertService.class), serviceConnection, Context.BIND_AUTO_CREATE);
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, MainApp.gs(R.string.insight_alert_notification_channel), NotificationManager.IMPORTANCE_HIGH);
channel.setSound(null, null);
notificationManager.createNotificationChannel(channel);
}
} }
@Override @Override
@ -671,8 +686,9 @@ public class LocalInsightPlugin extends PumpPluginBase implements PumpInterface,
cancelBolusMessage.setBolusID(bolusID); cancelBolusMessage.setBolusID(bolusID);
connectionService.requestMessage(cancelBolusMessage).await(); connectionService.requestMessage(cancelBolusMessage).await();
bolusCancelled = true; bolusCancelled = true;
confirmAlert(AlertType.WARNING_38);
alertService.ignore(null);
} }
confirmAlert(AlertType.WARNING_38);
} catch (AppLayerErrorException e) { } catch (AppLayerErrorException e) {
log.info("Exception while canceling bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); log.info("Exception while canceling bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")");
} catch (InsightException e) { } catch (InsightException e) {

View file

@ -12,19 +12,18 @@ import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import java.text.DecimalFormat;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.plugins.pump.insight.InsightAlertService; import info.nightscout.androidaps.plugins.pump.insight.InsightAlertService;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.Alert; import info.nightscout.androidaps.plugins.pump.insight.descriptors.Alert;
import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertStatus; import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertStatus;
import info.nightscout.androidaps.plugins.pump.insight.utils.AlertUtilsKt;
public class InsightAlertActivity extends NoSplashAppCompatActivity { public class InsightAlertActivity extends AppCompatActivity {
private Alert alert;
private InsightAlertService alertService; private InsightAlertService alertService;
private ImageView icon; private ImageView icon;
@ -38,10 +37,10 @@ public class InsightAlertActivity extends NoSplashAppCompatActivity {
@Override @Override
public void onServiceConnected(ComponentName name, IBinder binder) { public void onServiceConnected(ComponentName name, IBinder binder) {
alertService = ((InsightAlertService.LocalBinder) binder).getService(); alertService = ((InsightAlertService.LocalBinder) binder).getService();
alertService.setAlertActivity(InsightAlertActivity.this); alertService.getAlertLiveData().observe(InsightAlertActivity.this, alert -> {
alert = alertService.getAlert(); if (alert == null) finish();
if (alert == null) finish(); else update(alert);
else update(alert); });
} }
@Override @Override
@ -70,174 +69,22 @@ public class InsightAlertActivity extends NoSplashAppCompatActivity {
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.screenBrightness = 1.0F;
getWindow().setAttributes(layoutParams);
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
alertService.setAlertActivity(null);
unbindService(serviceConnection); unbindService(serviceConnection);
super.onDestroy(); super.onDestroy();
} }
public void update(Alert alert) { public void update(Alert alert) {
this.alert = alert;
mute.setEnabled(true); mute.setEnabled(true);
mute.setVisibility(alert.getAlertStatus() == AlertStatus.SNOOZED ? View.GONE : View.VISIBLE); mute.setVisibility(alert.getAlertStatus() == AlertStatus.SNOOZED ? View.GONE : View.VISIBLE);
confirm.setEnabled(true); confirm.setEnabled(true);
int icon = 0; this.icon.setImageDrawable(ContextCompat.getDrawable(this, AlertUtilsKt.getAlertIcon(alert.getAlertCategory())));
int code = 0; this.errorCode.setText(AlertUtilsKt.getAlertCode(alert.getAlertType()));
int title = 0; this.errorTitle.setText(AlertUtilsKt.getAlertTitle(alert.getAlertType()));
String description = null; String description = AlertUtilsKt.getAlertDescription(alert);
switch (alert.getAlertCategory()) {
case ERROR:
icon = R.drawable.ic_error;
break;
case MAINTENANCE:
icon = R.drawable.ic_maintenance;
break;
case WARNING:
icon = R.drawable.ic_warning;
break;
case REMINDER:
icon = R.drawable.ic_reminder;
break;
}
DecimalFormat decimalFormat = new DecimalFormat("##0.00");
int hours = alert.getTBRDuration() / 60;
int minutes = alert.getTBRDuration() - hours * 60;
switch (alert.getAlertType()) {
case REMINDER_01:
code = R.string.alert_r1_code;
title = R.string.alert_r1_title;
break;
case REMINDER_02:
code = R.string.alert_r2_code;
title = R.string.alert_r2_title;
break;
case REMINDER_03:
code = R.string.alert_r3_code;
title = R.string.alert_r3_title;
break;
case REMINDER_04:
code = R.string.alert_r4_code;
title = R.string.alert_r4_title;
break;
case REMINDER_07:
code = R.string.alert_r7_code;
title = R.string.alert_r7_title;
description = getString(R.string.alert_r7_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes));
break;
case WARNING_31:
code = R.string.alert_w31_code;
title = R.string.alert_w31_title;
description = getString(R.string.alert_w31_description, decimalFormat.format(alert.getCartridgeAmount()));
break;
case WARNING_32:
code = R.string.alert_w32_code;
title = R.string.alert_w32_title;
description = getString(R.string.alert_w32_description);
break;
case WARNING_33:
code = R.string.alert_w33_code;
title = R.string.alert_w33_title;
description = getString(R.string.alert_w33_description);
break;
case WARNING_34:
code = R.string.alert_w34_code;
title = R.string.alert_w34_title;
description = getString(R.string.alert_w34_description);
break;
case WARNING_36:
code = R.string.alert_w36_code;
title = R.string.alert_w36_title;
description = getString(R.string.alert_w36_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes));
break;
case WARNING_38:
code = R.string.alert_w38_code;
title = R.string.alert_w38_title;
description = getString(R.string.alert_w38_description, decimalFormat.format(alert.getProgrammedBolusAmount()), decimalFormat.format(alert.getDeliveredBolusAmount()));
break;
case WARNING_39:
code = R.string.alert_w39_code;
title = R.string.alert_w39_title;
break;
case MAINTENANCE_20:
code = R.string.alert_m20_code;
title = R.string.alert_m20_title;
description = getString(R.string.alert_m20_description);
break;
case MAINTENANCE_21:
code = R.string.alert_m21_code;
title = R.string.alert_m21_title;
description = getString(R.string.alert_m21_description);
break;
case MAINTENANCE_22:
code = R.string.alert_m22_code;
title = R.string.alert_m22_title;
description = getString(R.string.alert_m22_description);
break;
case MAINTENANCE_23:
code = R.string.alert_m23_code;
title = R.string.alert_m23_title;
description = getString(R.string.alert_m23_description);
break;
case MAINTENANCE_24:
code = R.string.alert_m24_code;
title = R.string.alert_m24_title;
description = getString(R.string.alert_m24_description);
break;
case MAINTENANCE_25:
code = R.string.alert_m25_code;
title = R.string.alert_m25_title;
description = getString(R.string.alert_m25_description);
break;
case MAINTENANCE_26:
code = R.string.alert_m26_code;
title = R.string.alert_m26_title;
description = getString(R.string.alert_m26_description);
break;
case MAINTENANCE_27:
code = R.string.alert_m27_code;
title = R.string.alert_m27_title;
description = getString(R.string.alert_m27_description);
break;
case MAINTENANCE_28:
code = R.string.alert_m28_code;
title = R.string.alert_m28_title;
description = getString(R.string.alert_m28_description);
break;
case MAINTENANCE_29:
code = R.string.alert_m29_code;
title = R.string.alert_m29_title;
description = getString(R.string.alert_m29_description);
break;
case MAINTENANCE_30:
code = R.string.alert_m30_code;
title = R.string.alert_m30_title;
description = getString(R.string.alert_m30_description);
break;
case ERROR_6:
code = R.string.alert_e6_code;
title = R.string.alert_e6_title;
description = getString(R.string.alert_e6_description);
break;
case ERROR_10:
code = R.string.alert_e10_code;
title = R.string.alert_e10_title;
description = getString(R.string.alert_e10_description);
break;
case ERROR_13:
code = R.string.alert_e13_code;
title = R.string.alert_e13_title;
description = getString(R.string.alert_e13_description);
break;
}
this.icon.setImageDrawable(ContextCompat.getDrawable(this, icon));
this.errorCode.setText(code);
this.errorTitle.setText(title);
if (description == null) this.errorDescription.setVisibility(View.GONE); if (description == null) this.errorDescription.setVisibility(View.GONE);
else { else {
this.errorDescription.setVisibility(View.VISIBLE); this.errorDescription.setVisibility(View.VISIBLE);

View file

@ -83,4 +83,24 @@ public class Alert {
public double getCartridgeAmount() { public double getCartridgeAmount() {
return cartridgeAmount; return cartridgeAmount;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Alert alert = (Alert) o;
if (alertId != alert.alertId) return false;
if (tbrAmount != alert.tbrAmount) return false;
if (tbrDuration != alert.tbrDuration) return false;
if (Double.compare(alert.programmedBolusAmount, programmedBolusAmount) != 0)
return false;
if (Double.compare(alert.deliveredBolusAmount, deliveredBolusAmount) != 0)
return false;
if (Double.compare(alert.cartridgeAmount, cartridgeAmount) != 0) return false;
if (alertCategory != alert.alertCategory) return false;
if (alertType != alert.alertType) return false;
return alertStatus == alert.alertStatus;
}
} }

View file

@ -0,0 +1,107 @@
package info.nightscout.androidaps.plugins.pump.insight.utils
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.pump.insight.descriptors.Alert
import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertCategory
import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType
import java.text.DecimalFormat
fun getAlertCode(alertType: AlertType) = MainApp.gs(when (alertType) {
AlertType.REMINDER_01 -> R.string.alert_r1_code
AlertType.REMINDER_02 -> R.string.alert_r2_code
AlertType.REMINDER_03 -> R.string.alert_r3_code
AlertType.REMINDER_04 -> R.string.alert_r4_code
AlertType.REMINDER_07 -> R.string.alert_r7_code
AlertType.WARNING_31 -> R.string.alert_w31_code
AlertType.WARNING_32 -> R.string.alert_w32_code
AlertType.WARNING_33 -> R.string.alert_w33_code
AlertType.WARNING_34 -> R.string.alert_w34_code
AlertType.WARNING_36 -> R.string.alert_w36_code
AlertType.WARNING_38 -> R.string.alert_w38_code
AlertType.WARNING_39 -> R.string.alert_w39_code
AlertType.MAINTENANCE_20 -> R.string.alert_m20_code
AlertType.MAINTENANCE_21 -> R.string.alert_m21_code
AlertType.MAINTENANCE_22 -> R.string.alert_m22_code
AlertType.MAINTENANCE_23 -> R.string.alert_m23_code
AlertType.MAINTENANCE_24 -> R.string.alert_m24_code
AlertType.MAINTENANCE_25 -> R.string.alert_m25_code
AlertType.MAINTENANCE_26 -> R.string.alert_m26_code
AlertType.MAINTENANCE_27 -> R.string.alert_m27_code
AlertType.MAINTENANCE_28 -> R.string.alert_m28_code
AlertType.MAINTENANCE_29 -> R.string.alert_m29_code
AlertType.MAINTENANCE_30 -> R.string.alert_m30_code
AlertType.ERROR_6 -> R.string.alert_e6_code
AlertType.ERROR_10 -> R.string.alert_e10_code
AlertType.ERROR_13 -> R.string.alert_e13_code
})
fun getAlertTitle(alertType: AlertType) = MainApp.gs(when (alertType) {
AlertType.REMINDER_01 -> R.string.alert_r1_title
AlertType.REMINDER_02 -> R.string.alert_r2_title
AlertType.REMINDER_03 -> R.string.alert_r3_title
AlertType.REMINDER_04 -> R.string.alert_r4_title
AlertType.REMINDER_07 -> R.string.alert_r7_title
AlertType.WARNING_31 -> R.string.alert_w31_title
AlertType.WARNING_32 -> R.string.alert_w32_title
AlertType.WARNING_33 -> R.string.alert_w33_title
AlertType.WARNING_34 -> R.string.alert_w34_title
AlertType.WARNING_36 -> R.string.alert_w36_title
AlertType.WARNING_38 -> R.string.alert_w38_title
AlertType.WARNING_39 -> R.string.alert_w39_title
AlertType.MAINTENANCE_20 -> R.string.alert_m20_title
AlertType.MAINTENANCE_21 -> R.string.alert_m21_title
AlertType.MAINTENANCE_22 -> R.string.alert_m22_title
AlertType.MAINTENANCE_23 -> R.string.alert_m23_title
AlertType.MAINTENANCE_24 -> R.string.alert_m24_title
AlertType.MAINTENANCE_25 -> R.string.alert_m25_title
AlertType.MAINTENANCE_26 -> R.string.alert_m26_title
AlertType.MAINTENANCE_27 -> R.string.alert_m27_title
AlertType.MAINTENANCE_28 -> R.string.alert_m28_title
AlertType.MAINTENANCE_29 -> R.string.alert_m29_title
AlertType.MAINTENANCE_30 -> R.string.alert_m30_title
AlertType.ERROR_6 -> R.string.alert_e6_title
AlertType.ERROR_10 -> R.string.alert_e10_title
AlertType.ERROR_13 -> R.string.alert_e13_title
})
fun getAlertDescription(alert: Alert): String? {
val decimalFormat = DecimalFormat("##0.00")
val hours = alert.tbrDuration / 60
val minutes = alert.tbrDuration - hours * 60
return when (alert.alertType!!) {
AlertType.REMINDER_01 -> null
AlertType.REMINDER_02 -> null
AlertType.REMINDER_03 -> null
AlertType.REMINDER_04 -> null
AlertType.REMINDER_07 -> MainApp.gs(R.string.alert_r7_description, alert.tbrAmount, DecimalFormat("#0").format(hours.toLong()) + ":" + DecimalFormat("00").format(minutes.toLong()))
AlertType.WARNING_31 -> MainApp.gs(R.string.alert_w31_description, decimalFormat.format(alert.cartridgeAmount))
AlertType.WARNING_32 -> MainApp.gs(R.string.alert_w32_description)
AlertType.WARNING_33 -> MainApp.gs(R.string.alert_w33_description)
AlertType.WARNING_34 -> MainApp.gs(R.string.alert_w34_description)
AlertType.WARNING_36 -> MainApp.gs(R.string.alert_w36_description, alert.tbrAmount, DecimalFormat("#0").format(hours.toLong()) + ":" + DecimalFormat("00").format(minutes.toLong()))
AlertType.WARNING_38 -> MainApp.gs(R.string.alert_w38_description, decimalFormat.format(alert.programmedBolusAmount), decimalFormat.format(alert.deliveredBolusAmount))
AlertType.WARNING_39 -> null
AlertType.MAINTENANCE_20 -> MainApp.gs(R.string.alert_m20_description)
AlertType.MAINTENANCE_21 -> MainApp.gs(R.string.alert_m21_description)
AlertType.MAINTENANCE_22 -> MainApp.gs(R.string.alert_m22_description)
AlertType.MAINTENANCE_23 -> MainApp.gs(R.string.alert_m23_description)
AlertType.MAINTENANCE_24 -> MainApp.gs(R.string.alert_m24_description)
AlertType.MAINTENANCE_25 -> MainApp.gs(R.string.alert_m25_description)
AlertType.MAINTENANCE_26 -> MainApp.gs(R.string.alert_m26_description)
AlertType.MAINTENANCE_27 -> MainApp.gs(R.string.alert_m27_description)
AlertType.MAINTENANCE_28 -> MainApp.gs(R.string.alert_m28_description)
AlertType.MAINTENANCE_29 -> MainApp.gs(R.string.alert_m29_description)
AlertType.MAINTENANCE_30 -> MainApp.gs(R.string.alert_m30_description)
AlertType.ERROR_6 -> MainApp.gs(R.string.alert_e6_description)
AlertType.ERROR_10 -> MainApp.gs(R.string.alert_e10_description)
AlertType.ERROR_13 -> MainApp.gs(R.string.alert_e13_description)
}
}
fun getAlertIcon(alertCategory: AlertCategory) = when (alertCategory) {
AlertCategory.ERROR -> R.drawable.ic_error
AlertCategory.MAINTENANCE -> R.drawable.ic_maintenance
AlertCategory.WARNING -> R.drawable.ic_warning
AlertCategory.REMINDER -> R.drawable.ic_reminder
}

View file

@ -25,8 +25,6 @@ public class NetworkChangeReceiver extends BroadcastReceiver {
private static EventNetworkChange lastEvent = null; private static EventNetworkChange lastEvent = null;
public static final NetworkChangeReceiver instance = new NetworkChangeReceiver();
@Override @Override
public void onReceive(final Context context, final Intent intent) { public void onReceive(final Context context, final Intent intent) {
EventNetworkChange event = grabNetworkStatus(context); EventNetworkChange event = grabNetworkStatus(context);

View file

@ -1701,5 +1701,6 @@
<string name="loop_smbexecution_time_label">SMB execution time</string> <string name="loop_smbexecution_time_label">SMB execution time</string>
<string name="loop_tbrrequest_time_label">Temp basal request time</string> <string name="loop_tbrrequest_time_label">Temp basal request time</string>
<string name="loop_tbrexecution_time_label">Temp basal execution time</string> <string name="loop_tbrexecution_time_label">Temp basal execution time</string>
<string name="insight_alert_notification_channel">Insight Pump Alerts</string>
</resources> </resources>

View file

@ -27,12 +27,10 @@
<item name="android:windowAnimationStyle">@android:style/Animation</item> <item name="android:windowAnimationStyle">@android:style/Animation</item>
</style> </style>
<style name="InsightAlertDialog" parent="Theme.AppCompat.Dialog"> <style name="InsightAlertDialog" parent="Theme.AppCompat.Dialog.MinWidth">
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item> <item name="colorAccent">@color/colorAccent</item>
<item name="android:windowMinWidthMajor">96%</item>
<item name="android:windowMinWidthMinor">96%</item>
</style> </style>
<style name="Theme.AppCompat.NoTitle" parent="Theme.AppCompat.NoActionBar"> <style name="Theme.AppCompat.NoTitle" parent="Theme.AppCompat.NoActionBar">

View file

@ -82,6 +82,11 @@ class DetailedBolusInfoStorageTest {
d = DetailedBolusInfoStorage.findDetailedBolusInfo(1070000, 4.0) d = DetailedBolusInfoStorage.findDetailedBolusInfo(1070000, 4.0)
assertNull(d) assertNull(d)
assertEquals(3, DetailedBolusInfoStorage.store.size) assertEquals(3, DetailedBolusInfoStorage.store.size)
// Use last, if bolus size is the same
setUp()
d = DetailedBolusInfoStorage.findDetailedBolusInfo(1070000, 5.0)
assertEquals(5.0, d!!.insulin, 0.01)
assertEquals(2, DetailedBolusInfoStorage.store.size)
} }