Merge pull request #178 from AdrianLxM/wear-bolus5

Wear Bolus
This commit is contained in:
Milos Kozak 2017-02-13 18:13:36 +01:00 committed by GitHub
commit c6b3fe9883
84 changed files with 3152 additions and 223 deletions

View file

@ -97,10 +97,18 @@ android {
wear {
dimension "wear"
buildConfigField "boolean", "WEAR", "true"
buildConfigField "boolean", "WEAR_CONTROL", "false"
}
wearcontrol {
dimension "wear"
buildConfigField "boolean", "WEAR", "true"
buildConfigField "boolean", "WEAR_CONTROL", "true"
}
nowear {
dimension "wear"
buildConfigField "boolean", "WEAR", "false"
buildConfigField "boolean", "WEAR_CONTROL", "false"
}
}
}
@ -115,7 +123,9 @@ allprojects {
}
dependencies {
wearWearApp project(path: ':wear', configuration: 'fullRelease')
wearWearApp project(path: ':wear', configuration: 'restrictedRelease')
wearcontrolWearApp project(path: ':wear', configuration: 'fullRelease')
compile fileTree(include: ['*.jar'], dir: 'libs')
compile('com.crashlytics.sdk.android:crashlytics:2.5.7@aar') {
transitive = true;

View file

@ -33,6 +33,7 @@
</intent-filter>
</activity>
<activity android:name=".PreferencesActivity" />
<activity android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity" android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".AgreementActivity" />
<activity android:name=".plugins.DanaR.History.DanaRHistoryActivity" />
<activity android:name=".plugins.DanaRKorean.History.DanaRHistoryActivity" />

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.events;
/**
* Created by adrian on 07/02/17.
*/
public class EventBolusRequested {
private double amount;
public EventBolusRequested (double amount){
this.amount = amount;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
}

View file

@ -30,6 +30,7 @@ import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventBolusRequested;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTreatmentChange;
@ -49,6 +50,7 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@ -439,6 +441,8 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
}
MainApp.bus().post(new EventBolusRequested(insulin));
PumpEnactResult result = activePump.deliverTreatment(insulin, carbs, context);
BolusProgressDialog.bolusEnded = true;
@ -478,12 +482,20 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
carbs = applyCarbsConstraints(carbs);
BolusProgressDialog bolusProgressDialog = null;
if (context != null) {
if (context != null ) {
bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setInsulin(insulin);
bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress");
} else {
Intent i = new Intent();
i.putExtra("insulin", insulin.doubleValue());
i.setClass(MainApp.instance(), BolusProgressHelperActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
MainApp.bus().post(new EventBolusRequested(insulin));
PumpEnactResult result = activePump.deliverTreatment(insulin, carbs, context);
BolusProgressDialog.bolusEnded = true;

View file

@ -29,6 +29,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
TextView statusView;
TextView stopPressedView;
ProgressBar progressBar;
BolusProgressHelperActivity helperActivity;
static double amount;
public static boolean bolusEnded = false;
@ -45,6 +46,10 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
bolusEnded = false;
}
public void setHelperActivity(BolusProgressHelperActivity activity){
this.helperActivity = activity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@ -71,6 +76,14 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
if (bolusEnded) dismiss();
}
@Override
public void dismiss(){
super.dismiss();
if (helperActivity!= null){
helperActivity.finish();
}
}
@Override
public void onPause() {
super.onPause();

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
/**
* Created by adrian on 09/02/17.
*/
public class BolusProgressHelperActivity extends AppCompatActivity {
public BolusProgressHelperActivity() {
super();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getIntent().getDoubleExtra("insulin", 0d);
BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setHelperActivity(this);
bolusProgressDialog.setInsulin(this.getIntent().getDoubleExtra("insulin", 0d));
bolusProgressDialog.show(this.getSupportFragmentManager(), "BolusProgress");
}
}

View file

@ -320,7 +320,7 @@ public class OverviewFragment extends Fragment {
final JSONObject boluscalcJSON = new JSONObject();
try {
boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date()));
boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date()));
boluscalcJSON.put("targetBGLow", wizard.targetBGLow);
boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh);
boluscalcJSON.put("isf", wizard.sens);

View file

@ -0,0 +1,433 @@
package info.nightscout.androidaps.plugins.Wear;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Handler;
import android.os.HandlerThread;
import android.preference.PreferenceManager;
import android.support.annotation.BoolRes;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.view.View;
import com.j256.ormlite.dao.Dao;
import org.json.JSONException;
import org.json.JSONObject;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.Date;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Overview.QuickWizard;
import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin;
import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
/**
* Created by adrian on 09/02/17.
*/
public class ActionStringHandler {
public static final int TIMEOUT = 65 * 1000;
private static long lastSentTimestamp = 0;
private static String lastConfirmActionString = null;
private static BolusWizard lastBolusWizard = null;
private static SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
private static HandlerThread handlerThread = new HandlerThread(FillDialog.class.getSimpleName());
static {
handlerThread.start();
}
public synchronized static void handleInitiate(String actionstring){
if(!BuildConfig.WEAR_CONTROL) return;
lastBolusWizard = null;
String rTitle = "CONFIRM"; //TODO: i18n
String rMessage = "";
String rAction = "";
// do the parsing and check constraints
String[] act = actionstring.split("\\s+");
if ("fillpreset".equals(act[0])) {
///////////////////////////////////// PRIME/FILL
double amount = 0d;
if ("1".equals(act[1])) {
amount = SafeParse.stringToDouble(DecimalFormatter.to2Decimal(SafeParse.stringToDouble(sp.getString("fill_button1", "0.3"))));
} else if ("2".equals(act[1])) {
amount = SafeParse.stringToDouble(DecimalFormatter.to2Decimal(SafeParse.stringToDouble(sp.getString("fill_button2", "0"))));
} else if ("3".equals(act[1])) {
amount = SafeParse.stringToDouble(DecimalFormatter.to2Decimal(SafeParse.stringToDouble(sp.getString("fill_button3", "0"))));
} else {
return;
}
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount);
rMessage += MainApp.instance().getString(R.string.primefill) + ": " + insulinAfterConstraints + "U";
if (insulinAfterConstraints - amount != 0)
rMessage += "\n" + MainApp.instance().getString(R.string.constraintapllied);
rAction += "fill " + insulinAfterConstraints;
} else if ("fill".equals(act[0])) {
////////////////////////////////////////////// PRIME/FILL
double amount = SafeParse.stringToDouble(act[1]);
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount);
rMessage += MainApp.instance().getString(R.string.primefill) + ": " + insulinAfterConstraints + "U";
if (insulinAfterConstraints - amount != 0)
rMessage += "\n" + MainApp.instance().getString(R.string.constraintapllied);
rAction += "fill " + insulinAfterConstraints;
} else if ("bolus".equals(act[0])) {
////////////////////////////////////////////// BOLUS
double insulin = SafeParse.stringToDouble(act[1]);
int carbs = SafeParse.stringToInt(act[2]);
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbs);
rMessage += MainApp.instance().getString(R.string.bolus) + ": " + insulinAfterConstraints + "U\n";
rMessage += MainApp.instance().getString(R.string.carbs) + ": " + carbsAfterConstraints + "g";
if ((insulinAfterConstraints - insulin != 0) || (carbsAfterConstraints - carbs != 0)) {
rMessage += "\n" + MainApp.instance().getString(R.string.constraintapllied);
}
rAction += "bolus " + insulinAfterConstraints + " " + carbsAfterConstraints;
} else if ("temptarget".equals(act[0])) {
///////////////////////////////////////////////////////// TEMPTARGET
boolean isMGDL = Boolean.parseBoolean(act[1]);
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
if (!(Config.APS && tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL))) {
sendError("TempTargets not possible! Please check your configuration.");
return;
}
if (profile == null) {
sendError("No profile found!");
return;
}
if(profile.getUnits().equals(Constants.MGDL) != isMGDL){
sendError("Different units used on watch and phone!");
return;
}
int duration = SafeParse.stringToInt(act[2]);
if (duration == 0){
rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?";
rAction = "temptarget true 0 0 0";
} else {
double low = SafeParse.stringToDouble(act[3]);
double high = SafeParse.stringToDouble(act[4]);
if(!isMGDL){
low *= Constants.MMOLL_TO_MGDL;
high *= Constants.MMOLL_TO_MGDL;
}
if (low < Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) {
sendError("Min-BG out of range!");
return;
}
if (high < Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
sendError("Max-BG out of range!");
return;
}
rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2];
rAction = actionstring;
}
} else if ("status".equals(act[0])) {
////////////////////////////////////////////// STATUS
rTitle = "STATUS";
rAction = "statusmessage";
if("pump".equals(act[1])){
rTitle += " PUMP";
rMessage = getPumpStatus();
} else if("loop".equals(act[1])){
rTitle += " LOOP";
rMessage = getLoopStatus();
} else if("targets".equals(act[1])){
rTitle += " TARGETS";
rMessage = getTargetsStatus();
}
} else if ("wizard".equals(act[0])) {
////////////////////////////////////////////// WIZARD
Integer carbsBeforeConstraints = SafeParse.stringToInt(act[1]);
Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbsBeforeConstraints);
if(carbsAfterConstraints - carbsBeforeConstraints !=0){
sendError("Carb constraint violation!"); return;
}
boolean useBG = Boolean.parseBoolean(act[2]);
boolean useBolusIOB = Boolean.parseBoolean(act[3]);
boolean useBasalIOB = Boolean.parseBoolean(act[4]);
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null) {
sendError("No profile found!"); return;
}
BgReading bgReading = GlucoseStatus.actualBg();
if(bgReading==null && useBG){
sendError("No recent BG to base calculation on!"); return;
}
DecimalFormat format = new DecimalFormat("0.00");
BolusWizard bolusWizard = new BolusWizard();
bolusWizard.doCalc(profile.getDefaultProfile(), carbsAfterConstraints, useBG?bgReading.valueToUnits(profile.getUnits()):0d, 0d, useBolusIOB, useBasalIOB);
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(bolusWizard.calculatedTotalInsulin);
if(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin !=0){
sendError("Insulin contraint violation!" +
"\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) +"!");
return;
}
double insulin = bolusWizard.calculatedTotalInsulin;
if(bolusWizard.calculatedTotalInsulin < 0) {
bolusWizard.calculatedTotalInsulin = 0d;
}
if(bolusWizard.calculatedTotalInsulin <=0 && bolusWizard.carbs <=0){
rAction = "info";
rTitle = "INFO";
} else {
rAction = actionstring;
}
rMessage += "Carbs: " + bolusWizard.carbs + "g";
rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U";
rMessage += "\n_____________";
rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): ";
rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U";
if(useBG)rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U";
if(useBolusIOB)rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulingFromBolusIOB) + "U";
if(useBasalIOB)rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulingFromBasalsIOB) + "U";
lastBolusWizard = bolusWizard;
} else return;
// send result
WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation(rTitle, rMessage, rAction);
lastSentTimestamp = System.currentTimeMillis();
lastConfirmActionString = rAction;
}
@NonNull
private static String getPumpStatus() {
return MainApp.getConfigBuilder().shortStatus(false);
}
@NonNull
private static String getLoopStatus() {
String ret = "";
// decide if enabled/disabled closed/open; what Plugin as APS?
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
if(activeloop != null && activeloop.isEnabled(activeloop.getType())) {
if (MainApp.getConfigBuilder().isClosedModeEnabled()) {
ret += "CLOSED LOOP\n";
} else {
ret += "OPEN LOOP\n";
}
final APSInterface aps = MainApp.getConfigBuilder().getActiveAPS();
ret += "APS: " + ((aps==null)?"NO APS SELECTED!":((PluginBase) aps).getName());
if(activeloop.lastRun != null){
if(activeloop.lastRun.lastAPSRun != null)
ret += "\nLast Run: " + DateUtil.timeString(activeloop.lastRun.lastAPSRun);
if(activeloop.lastRun.lastEnact != null)
ret += "\nLast Enact: " + DateUtil.timeString(activeloop.lastRun.lastEnact);
}
} else {
ret += "LOOP DISABLED\n";
}
return ret;
}
@NonNull
private static String getTargetsStatus() {
String ret = "";
if (!Config.APS){
return "Targets only apply in APS mode!";
}
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if (profile == null){
return "No profile set :(";
}
//Check for Temp-Target:
TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class);
if (Config.APS && tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) {
TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime());
if (tempTarget != null) {
ret += "Temp Target: " + NSProfile.toUnitsString(tempTarget.low, NSProfile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + NSProfile.toUnitsString(tempTarget.high, NSProfile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits());
ret += "\nuntil: " + DateUtil.timeString(tempTarget.getPlannedTimeEnd());
ret += "\n\n";
}
}
//Default Range/Target
String maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL;
String minBgDefault = Constants.MIN_BG_DEFAULT_MGDL;
String targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL;
if (!profile.getUnits().equals(Constants.MGDL)) {
maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL;
minBgDefault = Constants.MIN_BG_DEFAULT_MMOL;
targetBgDefault = Constants.TARGET_BG_DEFAULT_MMOL;
}
ret += "DEFAULT RANGE: ";
ret += sp.getString("openapsma_min_bg", minBgDefault) + " - " + sp.getString("openapsma_max_bg", maxBgDefault);
ret += " target: " + sp.getString("openapsma_target_bg", targetBgDefault);
return ret;
}
public synchronized static void handleConfirmation(String actionString){
if(!BuildConfig.WEAR_CONTROL) return;
//Guard from old or duplicate confirmations
if (lastConfirmActionString == null) return;
if (!lastConfirmActionString.equals(actionString)) return;
if (System.currentTimeMillis() - lastSentTimestamp > TIMEOUT) return;
lastConfirmActionString = null;
// do the parsing, check constraints and enact!
String[] act = actionString.split("\\s+");
if ("fill".equals(act[0])){
Double amount = SafeParse.stringToDouble(act[1]);
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount);
if(amount - insulinAfterConstraints != 0){
ToastUtils.showToastInUiThread(MainApp.instance(), "aborting: previously applied constraint changed");
sendError("aborting: previously applied constraint changed");
return;
}
doFillBolus(amount);
} else if ("temptarget".equals(act[0])) {
int duration = SafeParse.stringToInt(act[2]);
double low = SafeParse.stringToDouble(act[3]);
double high = SafeParse.stringToDouble(act[4]);
boolean isMGDL = Boolean.parseBoolean(act[1]);
if(!isMGDL){
low *= Constants.MMOLL_TO_MGDL;
high *= Constants.MMOLL_TO_MGDL;
}
generateTempTarget(duration, low, high);
} else if ("wizard".equals(act[0])){
//use last calculation as confirmed string matches
doBolus(lastBolusWizard.calculatedTotalInsulin, lastBolusWizard.carbs);
lastBolusWizard = null;
} else if ("bolus".equals(act[0])) {
double insulin = SafeParse.stringToDouble(act[1]);
int carbs = SafeParse.stringToInt(act[2]);
doBolus(insulin, carbs);
}
lastBolusWizard = null;
}
private static void generateTempTarget(int duration, double low, double high) {
TempTarget tempTarget = new TempTarget();
tempTarget.timeStart = new Date();
tempTarget.duration = duration;
tempTarget.reason = "WearPlugin";
if(tempTarget.duration != 0) {
tempTarget.low = low;
tempTarget.high = high;
} else {
tempTarget.low = 0;
tempTarget.high = 0;
}
tempTarget.setTimeIndex(tempTarget.getTimeIndex());
Dao<TempTarget, Long> dao = null;
try {
dao = MainApp.getDbHelper().getDaoTempTargets();
dao.createIfNotExists(tempTarget);
MainApp.bus().post(new EventTempTargetRangeChange());
//TODO: Nightscout-Treatment for Temp-Target!
//ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
} catch (SQLException e) {
e.printStackTrace();
}
}
private static void doFillBolus(final Double amount) {
//if(1==1)return;
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(amount, 0, null, false);
if (!result.success) {
sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) +
"\n" +
result.comment);
}
}
});
}
private static void doBolus(final Double amount, final Integer carbs) {
//if(1==1)return;
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(amount, carbs, null, true);
if (!result.success) {
sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) +
"\n" +
result.comment);
}
}
});
}
private synchronized static void sendError(String errormessage){
WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation("ERROR", errormessage, "error");
lastSentTimestamp = System.currentTimeMillis();
lastConfirmActionString = null;
lastBolusWizard = null;
}
}

View file

@ -7,6 +7,7 @@ import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventBolusRequested;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange;
@ -15,7 +16,9 @@ import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.Wear.wearintegration.WatchUpdaterService;
import info.nightscout.utils.ToastUtils;
/**
* Created by adrian on 17/11/16.
@ -141,6 +144,34 @@ public class WearPlugin implements PluginBase {
sendDataToWatch(false, true, false);
}
@Subscribe
public void onStatusEvent(final EventOverviewBolusProgress ev) {
Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS);
intent.putExtra("progresspercent", ev.percent);
intent.putExtra("progressstatus", ev.status);
ctx.startService(intent);
}
@Subscribe
public void onStatusEvent(final EventBolusRequested ev) {
String status = String.format(MainApp.sResources.getString(R.string.bolusrequested), ev.getAmount());
Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS);
intent.putExtra("progresspercent", 0);
intent.putExtra("progressstatus", status);
ctx.startService(intent);
}
public void requestActionConfirmation(String title, String message, String actionstring){
Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST);
intent.putExtra("title", title);
intent.putExtra("message", message);
intent.putExtra("actionstring", actionstring);
ctx.startService(intent);
}
public static boolean isEnabled() {
return fragmentEnabled;
}

View file

@ -31,6 +31,7 @@ import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Wear.ActionStringHandler;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DecimalFormatter;
@ -44,14 +45,23 @@ public class WatchUpdaterService extends WearableListenerService implements
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings");
public static final String ACTION_SEND_STATUS = WatchUpdaterService.class.getName().concat(".SendStatus");
public static final String ACTION_SEND_BASALS = WatchUpdaterService.class.getName().concat(".SendBasals");
public static final String ACTION_SEND_BOLUSPROGRESS = WatchUpdaterService.class.getName().concat(".BolusProgress");
public static final String ACTION_SEND_ACTIONCONFIRMATIONREQUEST = WatchUpdaterService.class.getName().concat(".ActionConfirmationRequest");
private GoogleApiClient googleApiClient;
public static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
public static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
private static final String WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus";
public static final String WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring";
public static final String WEARABLE_INITIATE_ACTIONSTRING_PATH = "/nightscout_watch_initiateactionstring";
private static final String OPEN_SETTINGS_PATH = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
boolean wear_integration = false;
@ -115,7 +125,15 @@ public class WatchUpdaterService extends WearableListenerService implements
sendStatus();
} else if (ACTION_SEND_BASALS.equals(action)) {
sendBasals();
} else {
} else if (ACTION_SEND_BOLUSPROGRESS.equals(action)){
sendBolusProgress(intent.getIntExtra("progresspercent", 0), intent.hasExtra("progressstatus")?intent.getStringExtra("progressstatus"):"");
} else if (ACTION_SEND_ACTIONCONFIRMATIONREQUEST.equals(action)){
String title = intent.getStringExtra("title");
String message = intent.getStringExtra("message");
String actionstring = intent.getStringExtra("actionstring");
sendActionConfirmationRequest(title, message, actionstring);
}
else {
sendData();
}
} else {
@ -135,11 +153,33 @@ public class WatchUpdaterService extends WearableListenerService implements
@Override
public void onMessageReceived(MessageEvent event) {
if (wear_integration) {
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH))
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
resendData();
}
if (event != null && event.getPath().equals(WEARABLE_CANCELBOLUS_PATH)) {
cancelBolus();
}
if (event != null && event.getPath().equals(WEARABLE_INITIATE_ACTIONSTRING_PATH)) {
String actionstring = new String(event.getData());
ToastUtils.showToastInUiThread(this, "Wear: " + actionstring);
ActionStringHandler.handleInitiate(actionstring);
}
if (event != null && event.getPath().equals(WEARABLE_CONFIRM_ACTIONSTRING_PATH)) {
String actionstring = new String(event.getData());
ToastUtils.showToastInUiThread(this, "Wear Confirm: " + actionstring);
ActionStringHandler.handleConfirmation(actionstring);
}
}
}
private void cancelBolus() {
PumpInterface pump = MainApp.getConfigBuilder();
pump.stopBolusDelivering();
}
private void sendData() {
BgReading lastBG = GlucoseStatus.lastBg();
@ -423,6 +463,40 @@ public class WatchUpdaterService extends WearableListenerService implements
}
}
private void sendBolusProgress(int progresspercent, String status) {
if (googleApiClient.isConnected()) {
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(BOLUS_PROGRESS_PATH);
//unique content
dataMapRequest.getDataMap().putDouble("timestamp", System.currentTimeMillis());
dataMapRequest.getDataMap().putString("bolusProgress", "bolusProgress");
dataMapRequest.getDataMap().putString("progressstatus", status);
dataMapRequest.getDataMap().putInt("progresspercent", progresspercent);
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
Log.e("BolusProgress", "No connection to wearable available!");
}
}
private void sendActionConfirmationRequest(String title, String message, String actionstring) {
if (googleApiClient.isConnected()) {
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(ACTION_CONFIRMATION_REQUEST_PATH);
//unique content
dataMapRequest.getDataMap().putDouble("timestamp", System.currentTimeMillis());
dataMapRequest.getDataMap().putString("actionConfirmationRequest", "actionConfirmationRequest");
dataMapRequest.getDataMap().putString("title", title);
dataMapRequest.getDataMap().putString("message", message);
dataMapRequest.getDataMap().putString("actionstring", actionstring);
ToastUtils.showToastInUiThread(this, "Requesting confirmation from wear: " + actionstring);
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
Log.e("confirmationRequest", "No connection to wearable available!");
}
}
private void sendStatus() {
if (googleApiClient.isConnected()) {

View file

@ -15,7 +15,7 @@ import info.nightscout.client.data.NSProfile;
public class BolusWizard {
// Inputs
JSONObject specificProfile = null;
Integer carbs = 0;
public Integer carbs = 0;
Double bg = 0d;
Double correction;
Boolean includeBolusIOB = true;

View file

@ -256,6 +256,7 @@
<string name="smscommunicator_calibrationreplywithcode" formatted="false">To send calibration %.2f reply with code %s</string>
<string name="smscommunicator_bolusfailed">Bolus failed</string>
<string name="bolusdelivered" formatted="false">Bolus %.2fU delivered successfully</string>
<string name="bolusrequested" formatted="false">Going to deliver %.2fU</string>
<string name="smscommunicator_bolusdelivered" formatted="false">Bolus %.2fU delivered successfully</string>
<string name="bolusdelivering" formatted="false">Delivering %.2fU</string>
<string name="smscommunicator_remotecommandsallowed">Allow remote commands via SMS</string>

View file

@ -16,4 +16,12 @@
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>
</resources>

View file

@ -30,6 +30,20 @@ android {
resValue "string", "label_xdrip_circle", "AAPS(Circle)"
resValue "string", "label_xdrip_activity", "AAPS Prefs."
resValue "string", "app_settings", "AAPS Settings"
buildConfigField "boolean", "WEAR_CONTROL", "true"
}
restricted {
applicationId = "info.nightscout.androidaps"
resValue "string", "label_xdrip", "AAPS"
resValue "string", "label_xdrip_large", "AAPS(Large)"
resValue "string", "label_xdrip_big_chart", "AAPS(BigChart)"
resValue "string", "label_xdrip_circle", "AAPS(Circle)"
resValue "string", "label_xdrip_activity", "AAPS Prefs."
resValue "string", "app_settings", "AAPS Settings"
buildConfigField "boolean", "WEAR_CONTROL", "false"
}
}
}

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.nightscout.androidaps" >
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.nightscout.androidaps">
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
@ -9,83 +11,124 @@
android:allowBackup="true"
android:icon="@drawable/ic_icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
android:theme="@android:style/Theme.DeviceDefault">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<service
android:name="info.nightscout.androidaps.BIGChart"
android:name=".watchfaces.BIGChart"
android:allowEmbedded="true"
android:label="@string/label_xdrip_big_chart"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_bigchart" />
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/watchface_bigchart" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service
android:name="info.nightscout.androidaps.Home"
android:name=".watchfaces.Home"
android:allowEmbedded="true"
android:label="@string/label_xdrip"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_graph" />
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/watchface_graph" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service
android:name="info.nightscout.androidaps.LargeHome"
android:name=".watchfaces.LargeHome"
android:allowEmbedded="true"
android:label="@string/label_xdrip_large"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_dark" />
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/watchface_dark" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service
android:name="info.nightscout.androidaps.CircleWatchface"
android:name=".watchfaces.CircleWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_circle"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_circle" />
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/watchface_circle" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service android:name="info.nightscout.androidaps.ListenerService">
<service android:name=".data.ListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<activity
android:name="info.nightscout.androidaps.NWPreferences"
android:label="@string/label_xdrip_activity" >
android:name=".interaction.menus.MainMenuActivity"
android:label="@string/label_actions_activity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".interaction.AAPSPreferences"
android:label="SETTINGS">
</activity>
<activity
android:name=".interaction.actions.WizardActivity"
android:label="Wizard">
</activity>
<activity
android:name=".interaction.menus.FillMenuActivity"
android:label="Fillmenu">
</activity>
<activity
android:name=".interaction.menus.StatusMenuActivity"
android:label="Status">
</activity>
<activity
android:name=".interaction.actions.BolusActivity"
android:label="Bolus">
</activity>
<activity
android:name=".interaction.actions.FillActivity"
android:label="Fill">
</activity>
<activity
android:name=".interaction.actions.TempTargetActivity"
android:label="TempTarget">
</activity>
</application>
</manifest>

View file

@ -1,155 +0,0 @@
package info.nightscout.androidaps;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
/**
* Created by emmablack on 12/26/14.
*/
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
private static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
private static final String OPEN_SETTINGS = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
private static final String ACTION_RESEND = "com.dexdrip.stephenblack.nightwatch.RESEND_DATA";
private static final String ACTION_RESEND_BULK = "com.dexdrip.stephenblack.nightwatch.RESEND_BULK_DATA";
GoogleApiClient googleApiClient;
private long lastRequest = 0;
public class DataRequester extends AsyncTask<Void, Void, Void> {
Context mContext;
DataRequester(Context context) {
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
if (googleApiClient.isConnected()) {
if (System.currentTimeMillis() - lastRequest > 20 * 1000) { // enforce 20-second debounce period
lastRequest = System.currentTimeMillis();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_RESEND_PATH, null);
}
}
} else
googleApiClient.connect();
return null;
}
}
public void requestData() {
new DataRequester(this).execute();
}
public void googleApiConnect() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wearable.API)
.build();
Wearable.MessageApi.addListener(googleApiClient, this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && ACTION_RESEND.equals(intent.getAction())) {
googleApiConnect();
requestData();
}
return START_STICKY;
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
DataMap dataMap;
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
String path = event.getDataItem().getUri().getPath();
if (path.equals(OPEN_SETTINGS)) {
Intent intent = new Intent(this, NWPreferences.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if (path.equals(NEW_STATUS_PATH)) {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("status", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else if (path.equals(BASAL_DATA_PATH)){
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("basals", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("data", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
}
}
}
public static void requestData(Context context) {
Intent intent = new Intent(context, ListenerService.class);
intent.setAction(ACTION_RESEND);
context.startService(intent);
}
@Override
public void onConnected(Bundle bundle) {
requestData();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onDestroy() {
super.onDestroy();
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
if (googleApiClient != null) {
Wearable.MessageApi.removeListener(googleApiClient, this);
}
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.data;
/**
* Created by adrian on 18/11/16.

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.data;
/**
* Created by emmablack on 1/7/15.

View file

@ -0,0 +1,438 @@
package info.nightscout.androidaps.data;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.interaction.AAPSPreferences;
import info.nightscout.androidaps.R;
/**
* Created by emmablack on 12/26/14.
*/
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
private static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
private static final String WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus";
public static final String WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring";
public static final String WEARABLE_INITIATE_ACTIONSTRING_PATH = "/nightscout_watch_initiateactionstring";
private static final String OPEN_SETTINGS = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
public static final int BOLUS_PROGRESS_NOTIF_ID = 001;
public static final int CONFIRM_NOTIF_ID = 002;
private static final String ACTION_RESEND = "com.dexdrip.stephenblack.nightwatch.RESEND_DATA";
private static final String ACTION_CANCELBOLUS = "com.dexdrip.stephenblack.nightwatch.CANCELBOLUS";
private static final String ACTION_CONFIRMATION = "com.dexdrip.stephenblack.nightwatch.CONFIRMACTION";
private static final String ACTION_INITIATE_ACTION = "com.dexdrip.stephenblack.nightwatch.INITIATE_ACTION";
private static final String ACTION_RESEND_BULK = "com.dexdrip.stephenblack.nightwatch.RESEND_BULK_DATA";
GoogleApiClient googleApiClient;
private long lastRequest = 0;
private DismissThread confirmThread;
private DismissThread bolusprogressThread;
public class DataRequester extends AsyncTask<Void, Void, Void> {
Context mContext;
DataRequester(Context context) {
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
if (googleApiClient.isConnected()) {
if (System.currentTimeMillis() - lastRequest > 20 * 1000) { // enforce 20-second debounce period
lastRequest = System.currentTimeMillis();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_RESEND_PATH, null);
}
}
} else {
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
if (googleApiClient.isConnected()) {
if (System.currentTimeMillis() - lastRequest > 20 * 1000) { // enforce 20-second debounce period
lastRequest = System.currentTimeMillis();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_RESEND_PATH, null);
}
}
}
}
return null;
}
}
public class BolusCancelTask extends AsyncTask<Void, Void, Void> {
Context mContext;
BolusCancelTask(Context context) {
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
}
} else {
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
}
}
}
return null;
}
}
public class MessageActionTask extends AsyncTask<Void, Void, Void> {
Context mContext;
String mActionstring;
String mMessagePath;
MessageActionTask(Context context, String messagePath, String actionstring) {
mContext = context;
mActionstring = actionstring;
mMessagePath = messagePath;
}
@Override
protected Void doInBackground(Void... params) {
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
}
} else {
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
}
}
}
return null;
}
}
public void requestData() {
new DataRequester(this).execute();
}
public void cancelBolus() {
new BolusCancelTask(this).execute();
}
private void sendConfirmActionstring(String actionstring) {
new MessageActionTask(this, WEARABLE_CONFIRM_ACTIONSTRING_PATH, actionstring).execute();
}
private void sendInitiateActionstring(String actionstring) {
new MessageActionTask(this, WEARABLE_INITIATE_ACTIONSTRING_PATH, actionstring).execute();
}
public void googleApiConnect() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wearable.API)
.build();
Wearable.MessageApi.addListener(googleApiClient, this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && ACTION_RESEND.equals(intent.getAction())) {
googleApiConnect();
requestData();
} else if(intent != null && ACTION_CANCELBOLUS.equals(intent.getAction())){
googleApiConnect();
//dismiss notification
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(ListenerService.this);
notificationManager.cancel(BOLUS_PROGRESS_NOTIF_ID);
//send cancel-request to phone.
cancelBolus();
} else if(intent != null && ACTION_CONFIRMATION.equals(intent.getAction())){
googleApiConnect();
//dismiss notification
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(ListenerService.this);
notificationManager.cancel(CONFIRM_NOTIF_ID);
String actionstring = intent.getStringExtra("actionstring");
sendConfirmActionstring(actionstring);
} else if(intent != null && ACTION_INITIATE_ACTION.equals(intent.getAction())){
googleApiConnect();
String actionstring = intent.getStringExtra("actionstring");
sendInitiateActionstring(actionstring);
}
return START_STICKY;
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
DataMap dataMap;
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
String path = event.getDataItem().getUri().getPath();
if (path.equals(OPEN_SETTINGS)) {
Intent intent = new Intent(this, AAPSPreferences.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if (path.equals(BOLUS_PROGRESS_PATH)) {
int progress = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getInt("progresspercent", 0);
String status = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("progressstatus", "");
showBolusProgress(progress, status);
} else if (path.equals(ACTION_CONFIRMATION_REQUEST_PATH)) {
String title = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("title");
String message = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("message");
String actionstring = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("actionstring");
showConfirmationDialog(title, message, actionstring);
}else if (path.equals(NEW_STATUS_PATH)) {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("status", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else if (path.equals(BASAL_DATA_PATH)){
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("basals", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("data", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
}
}
}
private void showBolusProgress(int progresspercent, String progresstatus) {
Intent cancelIntent = new Intent(this, ListenerService.class);
cancelIntent.setAction(ACTION_CANCELBOLUS);
PendingIntent cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, 0);;
long[] vibratePattern;
boolean vibreate = PreferenceManager
.getDefaultSharedPreferences(this).getBoolean("vibrateOnBolus", true);
if(vibreate){
vibratePattern = new long[]{0, 50, 1000};
} else {
vibratePattern = new long[]{0, 1, 1000};
}
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_icon)
.setContentTitle("Bolus Progress")
.setContentText(progresspercent + "% - " + progresstatus)
.setContentIntent(cancelPendingIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVibrate(vibratePattern)
.addAction(R.drawable.ic_cancel, "CANCEL BOLUS", cancelPendingIntent);
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
if(confirmThread != null){
confirmThread.invalidate();
}
notificationManager.notify(BOLUS_PROGRESS_NOTIF_ID, notificationBuilder.build());
notificationManager.cancel(CONFIRM_NOTIF_ID); // multiple watch setup
if (progresspercent == 100){
scheduleDismissBolusprogress(5);
}
}
private void showConfirmationDialog(String title, String message, String actionstring) {
if(confirmThread != null){
confirmThread.invalidate();
}
Intent actionIntent = new Intent(this, ListenerService.class);
actionIntent.setAction(ACTION_CONFIRMATION);
actionIntent.putExtra("actionstring", actionstring);
PendingIntent actionPendingIntent = PendingIntent.getService(this, 0, actionIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_UPDATE_CURRENT);;
long[] vibratePattern = new long[]{0, 100, 50, 100, 50};
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_icon)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(actionPendingIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVibrate(vibratePattern)
.addAction(R.drawable.ic_confirm, title, actionPendingIntent);
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
notificationManager.notify(CONFIRM_NOTIF_ID, notificationBuilder.build());
// keep the confirmation dialog open for one minute.
scheduleDismissConfirm(60);
}
private void scheduleDismissConfirm(final int seconds) {
if(confirmThread != null){
confirmThread.invalidate();
}
confirmThread = new DismissThread(CONFIRM_NOTIF_ID, seconds);
confirmThread.start();
}
private void scheduleDismissBolusprogress(final int seconds) {
if(confirmThread != null){
confirmThread.invalidate();
}
bolusprogressThread = new DismissThread(BOLUS_PROGRESS_NOTIF_ID, seconds);
bolusprogressThread.start();
}
private class DismissThread extends Thread{
private final int notificationID;
private final int seconds;
private boolean valid = true;
DismissThread(int notificationID, int seconds){
this.notificationID = notificationID;
this.seconds = seconds;
}
public synchronized void invalidate(){
valid = false;
}
@Override
public void run() {
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
//e.printStackTrace();
}
synchronized (this) {
if(valid) {
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(ListenerService.this);
notificationManager.cancel(notificationID);
}
}
}
}
public static void requestData(Context context) {
Intent intent = new Intent(context, ListenerService.class);
intent.setAction(ACTION_RESEND);
context.startService(intent);
}
public static void initiateAction(Context context, String actionstring) {
Intent intent = new Intent(context, ListenerService.class);
intent.putExtra("actionstring", actionstring);
intent.setAction(ACTION_INITIATE_ACTION);
context.startService(intent);
}
@Override
public void onConnected(Bundle bundle) {
requestData();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onDestroy() {
super.onDestroy();
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
if (googleApiClient != null) {
Wearable.MessageApi.removeListener(googleApiClient, this);
}
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.data;
/**
* Created by adrian on 17/11/16.

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.interaction;
import android.os.Bundle;
@ -7,7 +7,7 @@ import android.preference.PreferenceActivity;
import info.nightscout.androidaps.R;
import preference.WearPreferenceActivity;
public class NWPreferences extends WearPreferenceActivity {
public class AAPSPreferences extends WearPreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -15,4 +15,10 @@ public class NWPreferences extends WearPreferenceActivity {
addPreferencesFromResource(R.xml.preferences);
}
@Override
protected void onPause(){
super.onPause();
finish();
}
}

View file

@ -0,0 +1,123 @@
package info.nightscout.androidaps.interaction.actions;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.wearable.view.DotsPageIndicator;
import android.support.wearable.view.GridPagerAdapter;
import android.support.wearable.view.GridViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DecimalFormat;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
import info.nightscout.androidaps.interaction.utils.SafeParse;
/**
* Created by adrian on 09/02/17.
*/
public class BolusActivity extends ViewSelectorActivity {
PlusMinusEditText editCarbs;
PlusMinusEditText editInsulin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
final Resources res = getResources();
final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyGridViewPagerAdapter());
DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator);
dotsPageIndicator.setPager(pager);
}
@Override
protected void onPause() {
super.onPause();
finish();
}
private class MyGridViewPagerAdapter extends GridPagerAdapter {
@Override
public int getColumnCount(int arg0) {
return 3;
}
@Override
public int getRowCount() {
return 1;
}
@Override
public Object instantiateItem(ViewGroup container, int row, int col) {
if(col == 0){
final View view = getInflatedPlusMinusView(container);
double def = 0;
if (editInsulin != null){
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
}
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 30d, 0.1d, new DecimalFormat("#0.0"), false);
setLabelToPlusMinusView(view, "insulin");
container.addView(view);
return view;
} else if(col == 1){
final View view = getInflatedPlusMinusView(container);
double def = 0;
if (editCarbs != null){
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
}
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), false);
setLabelToPlusMinusView(view, "carbs");
container.addView(view);
return view;
} else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = (ImageView) view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "bolus " +SafeParse.stringToDouble(editInsulin.editText.getText().toString())
+ " " + SafeParse.stringToInt(editCarbs.editText.getText().toString());
ListenerService.initiateAction(BolusActivity.this, actionstring);
finish();
}
});
container.addView(view);
return view;
}
}
@Override
public void destroyItem(ViewGroup container, int row, int col, Object view) {
// Handle this to get the data before the view is destroyed?
// Object should still be kept by this, just setup for reinit?
container.removeView((View)view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
}
}

View file

@ -0,0 +1,111 @@
package info.nightscout.androidaps.interaction.actions;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.wearable.view.DotsPageIndicator;
import android.support.wearable.view.GridPagerAdapter;
import android.support.wearable.view.GridViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DecimalFormat;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
import info.nightscout.androidaps.interaction.utils.SafeParse;
/**
* Created by adrian on 09/02/17.
*/
public class FillActivity extends ViewSelectorActivity {
PlusMinusEditText editInsulin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
final Resources res = getResources();
final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyGridViewPagerAdapter());
DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator);
dotsPageIndicator.setPager(pager);
}
@Override
protected void onPause() {
super.onPause();
finish();
}
private class MyGridViewPagerAdapter extends GridPagerAdapter {
@Override
public int getColumnCount(int arg0) {
return 2;
}
@Override
public int getRowCount() {
return 1;
}
@Override
public Object instantiateItem(ViewGroup container, int row, int col) {
if(col == 0){
final View view = getInflatedPlusMinusView(container);
double def = 0d;
if (editInsulin != null){
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
}
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 30d, 0.1d, new DecimalFormat("#0.0"), false);
setLabelToPlusMinusView(view, "insulin");
container.addView(view);
return view;
} else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = (ImageView) view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "fill " +SafeParse.stringToDouble(editInsulin.editText.getText().toString());
ListenerService.initiateAction(FillActivity.this, actionstring);
finish();
}
});
container.addView(view);
return view;
}
}
@Override
public void destroyItem(ViewGroup container, int row, int col, Object view) {
// Handle this to get the data before the view is destroyed?
// Object should still be kept by this, just setup for reinit?
container.removeView((View)view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
}
}

View file

@ -0,0 +1,167 @@
package info.nightscout.androidaps.interaction.actions;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.wearable.view.DotsPageIndicator;
import android.support.wearable.view.GridPagerAdapter;
import android.support.wearable.view.GridViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DecimalFormat;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
import info.nightscout.androidaps.interaction.utils.SafeParse;
import static android.preference.PreferenceManager.getDefaultSharedPreferences;
/**
* Created by adrian on 09/02/17.
*/
public class TempTargetActivity extends ViewSelectorActivity {
PlusMinusEditText lowRange;
PlusMinusEditText highRange;
PlusMinusEditText time;
boolean isMGDL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
final Resources res = getResources();
final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyGridViewPagerAdapter());
DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator);
dotsPageIndicator.setPager(pager);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
isMGDL = sp.getBoolean("units_mgdl", true);
}
@Override
protected void onPause() {
super.onPause();
finish();
}
private class MyGridViewPagerAdapter extends GridPagerAdapter {
@Override
public int getColumnCount(int arg0) {
return 4;
}
@Override
public int getRowCount() {
return 1;
}
@Override
public Object instantiateItem(ViewGroup container, int row, int col) {
if(col == 0){
final View view = getInflatedPlusMinusView(container);
final TextView textView = (TextView) view.findViewById(R.id.label);
textView.setText("duration");
if (time == null) {
time = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 60d, 0d, 24 * 60d, 1d, new DecimalFormat("0"), false);
} else {
double def = SafeParse.stringToDouble(time.editText.getText().toString());
time = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 24 * 60d, 1d, new DecimalFormat("0"), false);
}
setLabelToPlusMinusView(view, "duration");
container.addView(view);
return view;
} else if(col == 1){
final View view = getInflatedPlusMinusView(container);
if (isMGDL){
double def = 100;
if (lowRange != null){
def = SafeParse.stringToDouble(lowRange.editText.getText().toString());
}
lowRange = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 72d, 180d, 1d, new DecimalFormat("0"), false);
} else {
double def = 5.5;
if (lowRange != null){
def = SafeParse.stringToDouble(lowRange.editText.getText().toString());
}
lowRange = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 4d, 10d, 0.1d, new DecimalFormat("#0.0"), false);
}
setLabelToPlusMinusView(view, "low");
container.addView(view);
return view;
} else if(col == 2){
final View view = getInflatedPlusMinusView(container);
if (isMGDL){
double def = 100;
if (highRange != null){
def = SafeParse.stringToDouble(highRange.editText.getText().toString());
}
highRange = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 72d, 180d, 1d, new DecimalFormat("0"), false);
} else {
double def = 5.5;
if (highRange != null){
def = SafeParse.stringToDouble(highRange.editText.getText().toString());
}
highRange = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 4d, 10d, 0.1d, new DecimalFormat("#0.0"), false);
}
setLabelToPlusMinusView(view, "high");
container.addView(view);
return view;
}else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = (ImageView) view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "temptarget "
+ " " + isMGDL
+ " " + SafeParse.stringToInt(time.editText.getText().toString())
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
+ " " + SafeParse.stringToDouble(highRange.editText.getText().toString())
;
ListenerService.initiateAction(TempTargetActivity.this, actionstring);
finish();
}
});
container.addView(view);
return view;
}
}
@Override
public void destroyItem(ViewGroup container, int row, int col, Object view) {
// Handle this to get the data before the view is destroyed?
// Object should still be kept by this, just setup for reinit?
container.removeView((View)view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
}
}

View file

@ -0,0 +1,51 @@
package info.nightscout.androidaps.interaction.actions;
import android.app.Activity;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import info.nightscout.androidaps.R;
/**
* Created by adrian on 13/02/17.
*/
public class ViewSelectorActivity extends Activity {
View getInflatedPlusMinusView(ViewGroup container) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
int design = Integer.parseInt(sharedPrefs.getString("input_design", "1"));
if (design == 2){
return LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_editplusminus_item_quickrighty, container, false);
} else if (design == 3) {
return LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_editplusminus_item_quicklefty, container, false);
} else if (design == 4) {
return LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_editplusminus_item_viktoria, container, false);
}
//default
return LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_editplusminus_item, container, false);
}
void setLabelToPlusMinusView(View view, String labelText){
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
int design = Integer.parseInt(sharedPrefs.getString("input_design", "1"));
if (design == 4){
//@LadyViktoria: Here the label can be set differently, if you like.
final TextView textView = (TextView) view.findViewById(R.id.label);
textView.setText(labelText);
} else {
final TextView textView = (TextView) view.findViewById(R.id.label);
textView.setText(labelText);
}
}
}

View file

@ -0,0 +1,192 @@
package info.nightscout.androidaps.interaction.actions;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.wearable.view.DotsPageIndicator;
import android.support.wearable.view.GridPagerAdapter;
import android.support.wearable.view.GridViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DecimalFormat;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
import info.nightscout.androidaps.interaction.utils.SafeParse;
/**
* Created by adrian on 09/02/17.
*/
public class WizardActivity extends ViewSelectorActivity {
PlusMinusEditText editCarbs;
boolean useBG;
boolean includeBolusIOB;
boolean includeBasalIOB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid_layout);
final Resources res = getResources();
final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyGridViewPagerAdapter());
DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator);
dotsPageIndicator.setPager(pager);
}
@Override
protected void onPause() {
super.onPause();
finish();
}
private class MyGridViewPagerAdapter extends GridPagerAdapter {
@Override
public int getColumnCount(int arg0) {
return 5;
}
@Override
public int getRowCount() {
return 1;
}
@Override
public Object instantiateItem(ViewGroup container, int row, int col) {
if(col == 0){
final View view = getInflatedPlusMinusView(container);
if (editCarbs == null) {
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 0d, 0d, 150d, 1d, new DecimalFormat("0"), false);
} else {
double def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), false);
}
setLabelToPlusMinusView(view, "carbs");
container.addView(view);
return view;
} else if(col == 1){
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_toggle_item, container, false);
final TextView textView = (TextView) view.findViewById(R.id.label);
textView.setText("include BG?");
final ImageView togglebutton = (ImageView) view.findViewById(R.id.togglebutton);
if(useBG){
togglebutton.setImageResource(R.drawable.ic_toggle_on);
} else {
togglebutton.setImageResource(R.drawable.ic_toggle_off);
}
togglebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
useBG = !useBG;
if(useBG){
togglebutton.setImageResource(R.drawable.ic_toggle_on);
} else {
togglebutton.setImageResource(R.drawable.ic_toggle_off);
}
}
});
container.addView(view);
return view;
} else if(col == 2){
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_toggle_item, container, false);
final TextView textView = (TextView) view.findViewById(R.id.label);
textView.setText("Bolus IOB?");
final ImageView togglebutton = (ImageView) view.findViewById(R.id.togglebutton);
if(includeBolusIOB){
togglebutton.setImageResource(R.drawable.ic_toggle_on);
} else {
togglebutton.setImageResource(R.drawable.ic_toggle_off);
}
togglebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
includeBolusIOB = !includeBolusIOB;
if(includeBolusIOB){
togglebutton.setImageResource(R.drawable.ic_toggle_on);
} else {
togglebutton.setImageResource(R.drawable.ic_toggle_off);
}
}
});
container.addView(view);
return view;
} else if(col == 3){
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_toggle_item, container, false);
final TextView textView = (TextView) view.findViewById(R.id.label);
textView.setText("Basal IOB?");
final ImageView togglebutton = (ImageView) view.findViewById(R.id.togglebutton);
if(includeBasalIOB){
togglebutton.setImageResource(R.drawable.ic_toggle_on);
} else {
togglebutton.setImageResource(R.drawable.ic_toggle_off);
}
togglebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
includeBasalIOB = !includeBasalIOB;
if(includeBasalIOB){
togglebutton.setImageResource(R.drawable.ic_toggle_on);
} else {
togglebutton.setImageResource(R.drawable.ic_toggle_off);
}
}
});
container.addView(view);
return view;
} else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = (ImageView) view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "wizard " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
+ " " + useBG
+ " " + includeBolusIOB
+ " " + includeBasalIOB;
ListenerService.initiateAction(WizardActivity.this, actionstring);
finish();
}
});
container.addView(view);
return view;
}
}
@Override
public void destroyItem(ViewGroup container, int row, int col, Object view) {
// Handle this to get the data before the view is destroyed?
// Object should still be kept by this, just setup for reinit?
container.removeView((View)view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
}
}

View file

@ -0,0 +1,45 @@
package info.nightscout.androidaps.interaction.menus;
import android.content.Intent;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.actions.FillActivity;
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
/**
* Created by adrian on 09/02/17.
*/
public class FillMenuActivity extends MenuListActivity {
@Override
protected String[] getElements() {
return new String[] {
"Preset 1",
"Preset 2",
"Preset 3",
"Free amount"
};
}
@Override
protected void doAction(int position) {
switch (position) {
case 0:
ListenerService.initiateAction(this, "fillpreset 1");
break;
case 1:
ListenerService.initiateAction(this, "fillpreset 2");
break;
case 2:
ListenerService.initiateAction(this, "fillpreset 3");
break;
case 3:
Intent intent = new Intent(this, FillActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
}
}
}

View file

@ -0,0 +1,112 @@
package info.nightscout.androidaps.interaction.menus;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.AAPSPreferences;
import info.nightscout.androidaps.interaction.actions.BolusActivity;
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
import info.nightscout.androidaps.interaction.actions.WizardActivity;
/**
* Created by adrian on 09/02/17.
*/
public class MainMenuActivity extends MenuListActivity {
SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
sp = PreferenceManager.getDefaultSharedPreferences(this);
super.onCreate(savedInstanceState);
ListenerService.requestData(this);
}
@Override
protected String[] getElements() {
if(!BuildConfig.WEAR_CONTROL){
return new String[] {
"Settings",
"Re-Sync"};
}
boolean showPrimeFill = sp.getBoolean("primefill", false);
return new String[] {
"TempT",
"Bolus",
"Wizard",
"Settings",
"Re-Sync",
"Status",
showPrimeFill?"Prime/Fill":""};
}
@Override
protected void doAction(int position) {
Intent intent;
if(!BuildConfig.WEAR_CONTROL) {
switch (position) {
case 0:
intent = new Intent(this, AAPSPreferences.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 1:
ListenerService.requestData(this);
break;
}
return;
}
switch (position) {
case 0:
intent = new Intent(this, TempTargetActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 1:
intent = new Intent(this, BolusActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 2:
intent = new Intent(this, WizardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 3:
intent = new Intent(this, AAPSPreferences.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 4:
ListenerService.requestData(this);
break;
case 5:
intent = new Intent(this, StatusMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 6:
boolean showPrimeFill = sp.getBoolean("primefill", false);
if(showPrimeFill) {
intent = new Intent(this, FillMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
break;
}
}
}

View file

@ -0,0 +1,53 @@
package info.nightscout.androidaps.interaction.menus;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.AAPSPreferences;
import info.nightscout.androidaps.interaction.actions.BolusActivity;
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
import info.nightscout.androidaps.interaction.actions.WizardActivity;
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
/**
* Created by adrian on 09/02/17.
*/
public class MainMenuRestrictedActivity extends MenuListActivity {
SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
sp = PreferenceManager.getDefaultSharedPreferences(this);
super.onCreate(savedInstanceState);
ListenerService.requestData(this);
}
@Override
protected String[] getElements() {
return new String[] {
"Settings",
"Re-Sync"};
}
@Override
protected void doAction(int position) {
Intent intent;
switch (position) {
case 0:
intent = new Intent(this, AAPSPreferences.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
break;
case 1:
ListenerService.requestData(this);
break;
}
}
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.interaction.menus;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.utils.MenuListActivity;
/**
* Created by adrian on 09/02/17.
*/
public class StatusMenuActivity extends MenuListActivity {
@Override
protected String[] getElements() {
return new String[] {
"Pump",
"Loop",
"Targets"};
}
@Override
protected void doAction(int position) {
switch (position) {
case 0:
ListenerService.initiateAction(this, "status pump");
break;
case 1:
ListenerService.initiateAction(this, "status loop");
break;
case 2:
ListenerService.initiateAction(this, "status targets");
break;
}
}
}

View file

@ -0,0 +1,120 @@
package info.nightscout.androidaps.interaction.utils;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.wearable.view.WearableListView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import info.nightscout.androidaps.R;
/**
* Created by adrian on 08/02/17.
*/
public abstract class MenuListActivity extends Activity
implements WearableListView.ClickListener {
String[] elements;
protected abstract String[] getElements();
protected abstract void doAction(int position);
@Override
protected void onPause(){
super.onPause();
finish();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
elements = getElements();
setContentView(R.layout.actions_list_activity);
// Get the list component from the layout of the activity
WearableListView listView =
(WearableListView) findViewById(R.id.wearable_list);
// Assign an adapter to the list
listView.setAdapter(new Adapter(this, elements));
// Set a click listener
listView.setClickListener(this);
}
// WearableListView click listener
@Override
public void onClick(WearableListView.ViewHolder v) {
Integer tag = (Integer) v.itemView.getTag();
doAction(tag);
//ActionsDefinitions.doAction(v.getAdapterPosition(), this);
finish();
}
@Override
public void onTopEmptyRegionClick() {
}
private static final class Adapter extends WearableListView.Adapter {
private String[] mDataset;
private final Context mContext;
private final LayoutInflater mInflater;
// Provide a suitable constructor (depends on the kind of dataset)
public Adapter(Context context, String[] dataset) {
mContext = context;
mInflater = LayoutInflater.from(context);
mDataset = dataset;
}
// Provide a reference to the type of views you're using
public static class ItemViewHolder extends WearableListView.ViewHolder {
private TextView textView;
public ItemViewHolder(View itemView) {
super(itemView);
// find the text view within the custom item's layout
textView = (TextView) itemView.findViewById(R.id.actionitem);
}
}
// Create new views for list items
// (invoked by the WearableListView's layout manager)
@Override
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// Inflate our custom layout for list items
return new ItemViewHolder(mInflater.inflate(R.layout.list_item, null));
}
// Replace the contents of a list item
// Instead of creating new views, the list tries to recycle existing ones
// (invoked by the WearableListView's layout manager)
@Override
public void onBindViewHolder(WearableListView.ViewHolder holder,
int position) {
// retrieve the text view
ItemViewHolder itemHolder = (ItemViewHolder) holder;
TextView view = itemHolder.textView;
// replace text contents
view.setText(mDataset[position]);
// replace list item's metadata
holder.itemView.setTag(position);
}
// Return the size of your dataset
// (invoked by the WearableListView's layout manager)
@Override
public int getItemCount() {
return mDataset.length;
}
}
}

View file

@ -0,0 +1,196 @@
package info.nightscout.androidaps.interaction.utils;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.NumberFormat;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by mike on 28.06.2016.
*/
public class PlusMinusEditText implements View.OnKeyListener,
View.OnTouchListener, View.OnClickListener {
Integer editTextID;
public TextView editText;
ImageView minusImage;
ImageView plusImage;
Double value;
Double minValue = 0d;
Double maxValue = 1d;
Double step = 1d;
NumberFormat formater;
boolean allowZero = false;
private Handler mHandler;
private ScheduledExecutorService mUpdater;
private class UpdateCounterTask implements Runnable {
private boolean mInc;
private int repeated = 0;
private int multiplier = 1;
private final int doubleLimit = 5;
public UpdateCounterTask(boolean inc) {
mInc = inc;
}
public void run() {
Message msg = new Message();
if (repeated % doubleLimit == 0) multiplier *= 2;
repeated++;
msg.arg1 = multiplier;
msg.arg2 = repeated;
if (mInc) {
msg.what = MSG_INC;
} else {
msg.what = MSG_DEC;
}
mHandler.sendMessage(msg);
}
}
private static final int MSG_INC = 0;
private static final int MSG_DEC = 1;
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero) {
editText = (TextView) view.findViewById(editTextID);
minusImage = (ImageView) view.findViewById(minusID);
plusImage = (ImageView) view.findViewById(plusID);
this.value = initValue;
this.minValue = minValue;
this.maxValue = maxValue;
this.step = step;
this.formater = formater;
this.allowZero = allowZero;
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INC:
inc(msg.arg1);
return;
case MSG_DEC:
dec(msg.arg1);
return;
}
super.handleMessage(msg);
}
};
minusImage.setOnTouchListener(this);
minusImage.setOnKeyListener(this);
minusImage.setOnClickListener(this);
plusImage.setOnTouchListener(this);
plusImage.setOnKeyListener(this);
plusImage.setOnClickListener(this);
updateEditText();
}
public void setValue(Double value) {
this.value = value;
updateEditText();
}
public Double getValue() {
return value;
}
public void setStep(Double step) {
this.step = step;
}
private void inc(int multiplier) {
value += step * multiplier;
if (value > maxValue) {
value = maxValue;
stopUpdating();
}
updateEditText();
}
private void dec( int multiplier) {
value -= step * multiplier;
if (value < minValue) {
value = minValue;
stopUpdating();
}
updateEditText();
}
private void updateEditText() {
if (value == 0d && !allowZero)
editText.setText("");
else
editText.setText(formater.format(value));
}
private void startUpdating(boolean inc) {
if (mUpdater != null) {
return;
}
mUpdater = Executors.newSingleThreadScheduledExecutor();
mUpdater.scheduleAtFixedRate(new UpdateCounterTask(inc), 200, 200,
TimeUnit.MILLISECONDS);
}
private void stopUpdating() {
if (mUpdater != null) {
mUpdater.shutdownNow();
mUpdater = null;
}
}
@Override
public void onClick(View v) {
if (mUpdater == null) {
if (v == plusImage) {
inc(1);
} else {
dec(1);
}
}
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER;
boolean isReleased = event.getAction() == KeyEvent.ACTION_UP;
boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN
&& event.getAction() != KeyEvent.ACTION_MULTIPLE;
if (isKeyOfInterest && isReleased) {
stopUpdating();
} else if (isKeyOfInterest && isPressed) {
startUpdating(v == plusImage);
}
return false;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
boolean isReleased = event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL;
boolean isPressed = event.getAction() == MotionEvent.ACTION_DOWN;
if (isReleased) {
stopUpdating();
} else if (isPressed) {
startUpdating(v == plusImage);
}
return false;
}
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.interaction.utils;
/**
* Created by mike on 23.06.2016.
*/
public class SafeParse {
public static Double stringToDouble(String input) {
Double result = 0d;
input = input.replace(",", ".");
try {
result = Double.parseDouble(input);
} catch (Exception e) {
}
return result;
}
public static Integer stringToInt(String input) {
Integer result = 0;
input = input.replace(",", ".");
try {
result = Integer.parseInt(input);
} catch (Exception e) {
}
return result;
}
public static Long stringToLong(String input) {
Long result = 0L;
input = input.replace(",", ".");
try {
result = Long.parseLong(input);
} catch (Exception e) {
}
return result;
}
}

View file

@ -0,0 +1,63 @@
package info.nightscout.androidaps.interaction.utils;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.support.wearable.view.WearableListView;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import info.nightscout.androidaps.R;
/**
* Created by adrian on 08/02/17.
*/
public class WearableListItemLayout extends LinearLayout
implements WearableListView.OnCenterProximityListener {
//private ImageView mCircle;
private TextView mName;
private final float mFadedTextAlpha;
private final int mFadedCircleColor;
private final int mChosenCircleColor;
public WearableListItemLayout(Context context) {
this(context, null);
}
public WearableListItemLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WearableListItemLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
mFadedTextAlpha = 40 / 100f;
mFadedCircleColor = getResources().getColor(R.color.grey);
mChosenCircleColor = getResources().getColor(R.color.blue);
}
// Get references to the icon and text in the item layout definition
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//mCircle = (ImageView) findViewById(R.id.circle);
mName = (TextView) findViewById(R.id.actionitem);
}
@Override
public void onCenterPosition(boolean animate) {
mName.setAlpha(1f);
//((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
}
@Override
public void onNonCenterPosition(boolean animate) {
//((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
mName.setAlpha(mFadedTextAlpha);
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.watchfaces;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -39,6 +39,12 @@ import com.ustwo.clockwise.common.WatchShape;
import java.util.ArrayList;
import java.util.Date;
import info.nightscout.androidaps.data.BasalWatchData;
import info.nightscout.androidaps.data.BgWatchData;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.TempWatchData;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
import lecho.lib.hellocharts.view.LineChartView;
/**
@ -83,6 +89,7 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
private String externalStatusString = "no status";
private TextView statusView;
private long chartTapTime = 0l;
private long sgvTapTime = 0l;
@Override
public void onCreate() {
@ -143,6 +150,8 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
if (tapType == TAP_TYPE_TAP&&
x >=chart.getLeft() &&
x <= chart.getRight()&&
@ -152,6 +161,17 @@ public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPre
changeChartTimeframe();
}
chartTapTime = eventTime;
} else if (tapType == TAP_TYPE_TAP&&
x + extra >=mSgv.getLeft() &&
x - extra <= mSgv.getRight()&&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()){
if (eventTime - sgvTapTime < 800){
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.watchfaces;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -34,6 +34,11 @@ import com.ustwo.clockwise.common.WatchShape;
import java.util.ArrayList;
import java.util.Date;
import info.nightscout.androidaps.data.BasalWatchData;
import info.nightscout.androidaps.data.BgWatchData;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.TempWatchData;
import lecho.lib.hellocharts.view.LineChartView;
/**

View file

@ -1,9 +1,8 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.watchfaces;
import android.content.Context;
import android.graphics.DashPathEffect;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.text.format.DateFormat;
import java.text.SimpleDateFormat;
@ -14,6 +13,9 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import info.nightscout.androidaps.data.BasalWatchData;
import info.nightscout.androidaps.data.BgWatchData;
import info.nightscout.androidaps.data.TempWatchData;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.watchfaces;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -17,6 +17,7 @@ import android.os.Bundle;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.wearable.watchface.WatchFaceStyle;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
@ -35,6 +36,10 @@ import java.util.Date;
import java.util.HashSet;
import java.util.TreeSet;
import info.nightscout.androidaps.data.BgWatchData;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
public class CircleWatchface extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
public final float PADDING = 20f;
@ -79,6 +84,8 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
private View myLayout;
protected SharedPreferences sharedPrefs;
private TextView mSgv;
private long sgvTapTime = 0;
@Override
@ -144,7 +151,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
// prepare fields
TextView textView = null;
mSgv = (TextView) myLayout.findViewById(R.id.sgvString);
textView = (TextView) myLayout.findViewById(R.id.sgvString);
if (sharedPrefs.getBoolean("showBG", true)) {
textView.setVisibility(View.VISIBLE);
@ -342,7 +349,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
}
public int getInRangeColor() {
if (sharedPrefs.getBoolean("dark", false)) {
if (sharedPrefs.getBoolean("dark", true)) {
return Color.argb(255, 120, 255, 120);
} else {
return Color.argb(255, 0, 240, 0);
@ -351,7 +358,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
}
public int getHighColor() {
if (sharedPrefs.getBoolean("dark", false)) {
if (sharedPrefs.getBoolean("dark", true)) {
return Color.argb(255, 255, 255, 120);
} else {
return Color.argb(255, 255, 200, 0);
@ -360,7 +367,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
}
public int getBackgroundColor() {
if (sharedPrefs.getBoolean("dark", false)) {
if (sharedPrefs.getBoolean("dark", true)) {
return Color.BLACK;
} else {
return Color.WHITE;
@ -369,7 +376,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
}
public int getTextColor() {
if (sharedPrefs.getBoolean("dark", false)) {
if (sharedPrefs.getBoolean("dark", true)) {
return Color.WHITE;
} else {
return Color.BLACK;
@ -662,7 +669,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
Log.d("CircleWatchface", "addReadingSoft");
double size;
int color = Color.LTGRAY;
if (sharedPrefs.getBoolean("dark", false)) {
if (sharedPrefs.getBoolean("dark", true)) {
color = Color.DKGRAY;
}
@ -680,7 +687,7 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
double size;
int color = Color.LTGRAY;
int indicatorColor = Color.DKGRAY;
if (sharedPrefs.getBoolean("dark", false)) {
if (sharedPrefs.getBoolean("dark", true)) {
color = Color.DKGRAY;
indicatorColor = Color.LTGRAY;
}
@ -700,4 +707,30 @@ public class CircleWatchface extends WatchFace implements SharedPreferences.OnSh
addArch(canvas, (float) size, offset * offsetMultiplier + 11, color, (float) (360f - size)); // Dark fill
addArch(canvas, (offset + .8f) * offsetMultiplier + 11, getBackgroundColor(), 360);
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
if (tapType == TAP_TYPE_TAP&&
x + extra >=mSgv.getLeft() &&
x - extra <= mSgv.getRight()&&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()){
if (eventTime - sgvTapTime < 800){
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
@Override
protected WatchFaceStyle getWatchFaceStyle(){
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
}

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.watchfaces;
import android.content.Intent;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.wearable.watchface.WatchFaceStyle;
@ -7,9 +8,13 @@ import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
public class Home extends BaseWatchFace {
private long chartTapTime = 0;
private long sgvTapTime = 0;
@Override
public void onCreate() {
@ -22,6 +27,8 @@ public class Home extends BaseWatchFace {
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
if (tapType == TAP_TYPE_TAP&&
x >=chart.getLeft() &&
x <= chart.getRight()&&
@ -31,6 +38,17 @@ public class Home extends BaseWatchFace {
changeChartTimeframe();
}
chartTapTime = eventTime;
} else if (tapType == TAP_TYPE_TAP&&
x + extra >=mSgv.getLeft() &&
x - extra <= mSgv.getRight()&&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()){
if (eventTime - sgvTapTime < 800){
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}

View file

@ -1,13 +1,20 @@
package info.nightscout.androidaps;
package info.nightscout.androidaps.watchfaces;
import android.content.Intent;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
public class LargeHome extends BaseWatchFace {
private long sgvTapTime = 0;
@Override
public void onCreate() {
super.onCreate();
@ -16,6 +23,30 @@ public class LargeHome extends BaseWatchFace {
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
if (tapType == TAP_TYPE_TAP&&
x + extra >=mSgv.getLeft() &&
x - extra <= mSgv.getRight()&&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()){
if (eventTime - sgvTapTime < 800){
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
@Override
protected WatchFaceStyle getWatchFaceStyle(){
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
@Override
protected void setColorDark(){
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mLinearLayout));

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:shape="oval">
<solid android:color="@android:color/transparent"/>
<stroke
android:width="2dip"
android:color="@color/cardObjectiveText"
/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/wl_gray"/>
</shape>

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:id="@+id/minusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_minus"
android:tint="#ffffff" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<EditText
android:id="@+id/amountfield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inputType="numberDecimal"
android:minWidth="50dp"
android:padding="10dp"
android:text="112"
android:textSize="45sp"
android:cursorVisible="false"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:textSize="25sp" />
</LinearLayout>
<ImageView
android:id="@+id/plusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_add"
android:tint="#ffffff" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<EditText
android:id="@+id/amountfield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inputType="numberDecimal"
android:minWidth="50dp"
android:text="112"
android:textSize="45sp"
android:cursorVisible="false"
android:gravity="center" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:textSize="25sp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:id="@+id/minusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_minus"
android:tint="#ffffff" />
<ImageView
android:id="@+id/plusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_add"
android:tint="#ffffff" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:id="@+id/plusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_add"
android:tint="#ffffff" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<EditText
android:id="@+id/amountfield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inputType="numberDecimal"
android:minWidth="100dp"
android:paddingTop="10dp"
android:text="112"
android:textSize="45sp"
android:cursorVisible="false"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:textSize="25sp" />
<ImageView
android:id="@+id/minusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_minus"
android:tint="#ffffff" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<EditText
android:id="@+id/amountfield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inputType="numberDecimal"
android:minWidth="100dp"
android:paddingTop="10dp"
android:text="112"
android:textSize="45sp"
android:cursorVisible="false"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:textSize="25sp" />
<ImageView
android:id="@+id/minusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_minus"
android:tint="#ffffff" />
</LinearLayout>
<ImageView
android:id="@+id/plusbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_add"
android:tint="#ffffff" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1">
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="left|center_vertical"
android:gravity="center"
android:rotation="90"
android:text="label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="25sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical|center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/plusbutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_add"
android:tint="#ffffff" />
<EditText
android:id="@+id/amountfield"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:background="@android:color/transparent"
android:cursorVisible="false"
android:gravity="center_vertical|center_horizontal"
android:inputType="numberDecimal"
android:minWidth="50dp"
android:padding="10dp"
android:text="112"
android:textSize="45sp" />
<ImageView
android:id="@+id/minusbutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_action_minus"
android:tint="#ffffff" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:id="@+id/confirmbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_confirm"
android:tint="#ffffff"
android:padding="25sp"
android:layout_margin="10sp"/>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"/>
<ImageView
android:id="@+id/togglebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/circle"
android:backgroundTint="#ffffff"
android:src="@drawable/ic_toggle_off"
android:tint="#ffffff"
android:padding="25sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=" "
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"/>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,21 @@
<android.support.wearable.view.BoxInsetLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/nslogo_background"
android:layout_height="match_parent"
android:layout_width="match_parent">
<FrameLayout
android:id="@+id/frame_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"
app:layout_box="left|bottom|right">
<android.support.wearable.view.WearableListView
android:id="@+id/wearable_list"
android:layout_height="match_parent"
android:layout_width="match_parent">
</android.support.wearable.view.WearableListView>
</FrameLayout>
</android.support.wearable.view.BoxInsetLayout>

View file

@ -8,5 +8,5 @@
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_bigchart"
app:roundLayout="@layout/round_activity_bigchart"
tools:context=".Home"
tools:context=".watchfaces.Home"
tools:deviceIds="wear"/>

View file

@ -8,5 +8,5 @@
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_home"
app:roundLayout="@layout/round_activity_home"
tools:context=".Home"
tools:context=".watchfaces.Home"
tools:deviceIds="wear"/>

View file

@ -8,5 +8,5 @@
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_home_large"
app:roundLayout="@layout/round_activity_home_large"
tools:context=".Home"
tools:context=".watchfaces.Home"
tools:deviceIds="wear"/>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.wearable.view.GridViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true" />
<android.support.wearable.view.DotsPageIndicator
android:id="@+id/page_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom">
</android.support.wearable.view.DotsPageIndicator>
</FrameLayout>

View file

@ -0,0 +1,24 @@
<info.nightscout.androidaps.interaction.utils.WearableListItemLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="80dp">
<!-- ImageView
android:id="@+id/circle"
android:layout_height="20dp"
android:layout_margin="16dp"
android:layout_width="20dp"
android:src="@drawable/wl_circle"/-->
<TextView
android:id="@+id/actionitem"
android:gravity="center_vertical|center_horizontal"
android:layout_width="match_parent"
android:layout_marginRight="16dp"
android:layout_marginLeft="16dp"
android:layout_height="match_parent"
android:fontFamily="sans-serif-condensed-light"
android:lineSpacingExtra="-4sp"
android:textColor="@color/dark_statusView"
android:textSize="32sp"/>
</info.nightscout.androidaps.interaction.utils.WearableListItemLayout>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_round"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_round"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_round"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_round"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="wl_blue">#2878ff</color>
<color name="wl_gray">#c1c1c1</color>
<color name="text_color">#434343</color>
<color name="cardObjectiveText">#779ECB</color>
<!-- light colors -->
<color name="light_bigchart_time">@color/black</color>
<color name="light_bigchart_status">@color/black</color>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">AAPS Prefs.</string>
<string name="app_name">AAPS</string>
<string name="label_actions_activity">AAPS</string>
<string-array name="chart_timeframe">
<item>1 hour</item>
@ -19,4 +20,27 @@
<item>5</item>
</string-array>
<string-array name="input_design">
<item>Default</item>
<item>Quick righty</item>
<item>Quick lefty</item>
<item>Modern Sparse</item>
</string-array>
<string-array name="input_design_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</string-array>
<string name="title_activity_bolus">BolusActivity</string>
<string name="hello_round">Hello Round World!</string>
<string name="hello_square">Hello Square World!</string>
</resources>

View file

@ -1,6 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<CheckBoxPreference
android:defaultValue="true"
android:key="vibrateOnBolus"
android:title="Vibrate on Bolus"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
<CheckBoxPreference
android:defaultValue="true"
android:key="units_mgdl"
android:title="Units for Actions"
android:summaryOn="mg/dl"
android:summaryOff="mmol/l"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
<ListPreference
android:defaultValue="1"
android:entries="@array/input_design"
android:entryValues="@array/input_design_values"
android:key="input_design"
android:summary="Input Design"
android:title="Input Design" />
<CheckBoxPreference
android:defaultValue="true"
android:key="showExternalStatus"
@ -88,7 +113,6 @@
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="animation"
@ -96,4 +120,12 @@
android:title="Animations"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="primefill"
android:summary="Prime/Fill from watch possible"
android:title="Prime in Menu"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
</PreferenceScreen>