Merge pull request #994 from MilosKozak/startupwizard

Startupwizard
This commit is contained in:
Milos Kozak 2018-05-22 23:07:04 +02:00 committed by GitHub
commit fa2c0ab003
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
65 changed files with 1981 additions and 249 deletions

View file

@ -49,7 +49,7 @@ def generateGitBuild = { ->
return stringBuilder.toString() return stringBuilder.toString()
} }
tasks.matching {it instanceof Test}.all { tasks.matching { it instanceof Test }.all {
testLogging.events = ["failed", "skipped", "started"] testLogging.events = ["failed", "skipped", "started"]
testLogging.exceptionFormat = "full" testLogging.exceptionFormat = "full"
} }
@ -89,7 +89,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
debug { debug {
testCoverageEnabled (project.hasProperty('coverage') ? true : false) testCoverageEnabled(project.hasProperty('coverage') ? true : false)
} }
} }
productFlavors { productFlavors {
@ -156,7 +156,7 @@ android {
unitTests.returnDefaultValues = true unitTests.returnDefaultValues = true
unitTests.includeAndroidResources = true unitTests.includeAndroidResources = true
} }
} }
allprojects { allprojects {
repositories { repositories {
@ -242,7 +242,7 @@ dependencies {
} }
task unzip(type: Copy) { task unzip(type: Copy) {
def zipPath = configurations.libs.find {it.name.startsWith("danars") } def zipPath = configurations.libs.find { it.name.startsWith("danars") }
def zipFile = file(zipPath) def zipFile = file(zipPath)
def outputDir = file("${buildDir}/unpacked/dist") def outputDir = file("${buildDir}/unpacked/dist")

View file

@ -53,12 +53,14 @@
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity"> <activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
<intent-filter> <intent-filter>
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" /> <action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".plugins.PumpDanaRS.activities.BLEScanActivity"> <activity android:name=".plugins.PumpDanaRS.activities.BLEScanActivity">
<intent-filter> <intent-filter>
<action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" /> <action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
@ -70,6 +72,7 @@
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<!-- Receive new SMS messages --> <!-- Receive new SMS messages -->
<action android:name="android.provider.Telephony.SMS_RECEIVED" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" />
<!-- Receiver from xDrip --> <!-- Receiver from xDrip -->
@ -140,7 +143,7 @@
<service <service
android:name=".plugins.PumpDanaRS.services.DanaRSService" android:name=".plugins.PumpDanaRS.services.DanaRSService"
android:enabled="true" android:enabled="true"
android:exported="true"></service> android:exported="true" />
<service <service
android:name=".plugins.Wear.wearintegration.WatchUpdaterService" android:name=".plugins.Wear.wearintegration.WatchUpdaterService"
android:exported="true"> android:exported="true">
@ -158,12 +161,17 @@
android:exported="true" /> android:exported="true" />
<service <service
android:name=".plugins.Overview.notifications.DismissNotificationService" android:name=".plugins.Overview.notifications.DismissNotificationService"
android:exported="false"></service> android:exported="false" />
<meta-data <meta-data
android:name="io.fabric.ApiKey" android:name="io.fabric.ApiKey"
android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" /> android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" />
<activity
android:name=".setupwizard.SetupWizardActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/AppTheme.SetupWizard"
android:label="@string/title_activity_setup_wizard"></activity>
</application> </application>
</manifest> </manifest>

View file

@ -1,20 +1,15 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Rect; import android.graphics.Rect;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.PowerManager; import android.os.PowerManager;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
@ -49,26 +44,20 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.SlidingTabLayout; import info.nightscout.androidaps.tabs.SlidingTabLayout;
import info.nightscout.androidaps.tabs.TabPageAdapter; import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.utils.AndroidPermission;
import info.nightscout.utils.ImportExportPrefs; import info.nightscout.utils.ImportExportPrefs;
import info.nightscout.utils.LocaleHelper; import info.nightscout.utils.LocaleHelper;
import info.nightscout.utils.LogDialog; import info.nightscout.utils.LogDialog;
import info.nightscout.utils.OKDialog; import info.nightscout.utils.OKDialog;
import info.nightscout.utils.PasswordProtection; import info.nightscout.utils.PasswordProtection;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
public class MainActivity extends AppCompatActivity implements View.OnClickListener { public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(MainActivity.class); private static Logger log = LoggerFactory.getLogger(MainActivity.class);
static final int CASE_STORAGE = 0x1;
static final int CASE_SMS = 0x2;
static final int CASE_LOCATION = 0x3;
private boolean askForSMS = false;
private boolean askForLocation = true;
ImageButton menuButton; ImageButton menuButton;
protected PowerManager.WakeLock mWakeLock; protected PowerManager.WakeLock mWakeLock;
@ -76,28 +65,51 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (Config.logFunctionCalls)
log.debug("onCreate");
Iconify.with(new FontAwesomeModule()); Iconify.with(new FontAwesomeModule());
LocaleHelper.onCreate(this, "en"); LocaleHelper.onCreate(this, "en");
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
menuButton = (ImageButton) findViewById(R.id.overview_menuButton); menuButton = (ImageButton) findViewById(R.id.overview_menuButton);
menuButton.setOnClickListener(this); menuButton.setOnClickListener(this);
checkEula();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
}
askForBatteryOptimizationPermission();
doMigrations();
if (Config.logFunctionCalls)
log.debug("onCreate");
onStatusEvent(new EventSetWakeLock(SP.getBoolean("lockscreen", false))); onStatusEvent(new EventSetWakeLock(SP.getBoolean("lockscreen", false)));
doMigrations();
registerBus(); registerBus();
setUpTabs(false); setUpTabs(false);
} }
@Override
protected void onResume() {
super.onResume();
if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) {
Intent intent = new Intent(this, SetupWizardActivity.class);
startActivity(intent);
} else {
checkEula();
}
AndroidPermission.notifyForStoragePermission(this);
AndroidPermission.notifyForBatteryOptimizationPermission(this);
AndroidPermission.notifyForLocationPermissions(this);
AndroidPermission.notifyForSMSPermissions(this);
MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
}
@Override
public void onDestroy() {
if (mWakeLock != null)
if (mWakeLock.isHeld())
mWakeLock.release();
super.onDestroy();
}
@Subscribe @Subscribe
public void onStatusEvent(final EventSetWakeLock ev) { public void onStatusEvent(final EventSetWakeLock ev) {
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
@ -205,120 +217,22 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
//check for sms permission if enable in prefernces
@Subscribe
public void onStatusEvent(final EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_smscommunicator_remotecommandsallowed)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
synchronized (this) {
if (SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)) {
setAskForSMS();
}
}
}
}
}
private synchronized void setAskForSMS() {
askForSMS = true;
}
@Override
protected void onResume() {
super.onResume();
askForSMSPermissions();
askForLocationPermissions();
MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
}
@Override
public void onDestroy() {
if (mWakeLock != null)
if (mWakeLock.isHeld())
mWakeLock.release();
super.onDestroy();
}
private void askForBatteryOptimizationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final String packageName = getPackageName();
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
log.debug("Requesting ignore battery optimization");
OKDialog.show(this, MainApp.gs(R.string.pleaseallowpermission), String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), new Runnable() {
@Override
public void run() {
try {
final Intent intent = new Intent();
// ignoring battery optimizations required for constant connection
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
} catch (ActivityNotFoundException e) {
final String msg = MainApp.gs(R.string.batteryoptimalizationerror);
ToastUtils.showToastInUiThread(getApplicationContext(), msg);
log.error(msg);
}
}
});
}
}
}
private synchronized void askForSMSPermissions() {
if (askForSMS) { //only when settings were changed an MainActivity resumes.
askForSMS = false;
if (SP.getBoolean(R.string.smscommunicator_remotecommandsallowed, false)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(new String[]{Manifest.permission.RECEIVE_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_MMS}, CASE_SMS);
}
}
}
}
private synchronized void askForLocationPermissions() {
if (askForLocation) { //only when settings were changed an MainActivity resumes.
askForLocation = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
askForPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION}, CASE_LOCATION);
}
}
}
private void askForPermission(String[] permission, Integer requestCode) {
boolean test = false;
for (int i = 0; i < permission.length; i++) {
test = test || (ContextCompat.checkSelfPermission(this, permission[i]) != PackageManager.PERMISSION_GRANTED);
}
if (test) {
ActivityCompat.requestPermissions(this, permission, requestCode);
}
}
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length != 0) { if (permissions.length != 0) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
switch (requestCode) { switch (requestCode) {
case CASE_STORAGE: case AndroidPermission.CASE_STORAGE:
//show dialog after permission is granted //show dialog after permission is granted
AlertDialog.Builder alert = new AlertDialog.Builder(this); AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setMessage(R.string.alert_dialog_storage_permission_text); alert.setMessage(R.string.alert_dialog_storage_permission_text);
alert.setPositiveButton(R.string.ok, null); alert.setPositiveButton(R.string.ok, null);
alert.show(); alert.show();
break; break;
case CASE_LOCATION: case AndroidPermission.CASE_LOCATION:
case CASE_SMS: case AndroidPermission.CASE_SMS:
case AndroidPermission.CASE_BATTERY:
break; break;
} }
} }
@ -368,6 +282,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.nav_historybrowser: case R.id.nav_historybrowser:
startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class)); startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
break; break;
case R.id.nav_setupwizard:
startActivity(new Intent(v.getContext(), SetupWizardActivity.class));
break;
case R.id.nav_resetdb: case R.id.nav_resetdb:
new AlertDialog.Builder(v.getContext()) new AlertDialog.Builder(v.getContext())
.setTitle(R.string.nav_resetdb) .setTitle(R.string.nav_resetdb)
@ -410,13 +327,13 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
if (MainApp.engineeringMode) if (MainApp.engineeringMode)
message += "\n" + MainApp.gs(R.string.engineering_mode_enabled); message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
message += MainApp.gs(R.string.about_link_urls); message += MainApp.gs(R.string.about_link_urls);
final SpannableString messageSpanned = new SpannableString(message); final SpannableString messageSpanned = new SpannableString(message);
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS); Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
builder.setMessage(messageSpanned); builder.setMessage(messageSpanned);
builder.setPositiveButton(MainApp.gs(R.string.ok), null); builder.setPositiveButton(MainApp.gs(R.string.ok), null);
AlertDialog alertDialog = builder.create(); AlertDialog alertDialog = builder.create();
alertDialog.show(); alertDialog.show();
((TextView)alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); ((TextView) alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
break; break;
case R.id.nav_exit: case R.id.nav_exit:
log.debug("Exiting"); log.debug("Exiting");

View file

@ -0,0 +1,4 @@
package info.nightscout.androidaps.events;
public class EventProfileStoreChanged extends Event {
}

View file

@ -285,7 +285,7 @@ public class ConfigBuilderFragment extends SubscriberFragment {
holder.checkboxEnabled.setEnabled(false); holder.checkboxEnabled.setEnabled(false);
} }
if (plugin.pluginDescription.alwayVisible) { if (plugin.pluginDescription.alwayVisible) {
holder.checkboxEnabled.setEnabled(false); holder.checkboxEnabled.setEnabled(false);
} }
@ -339,7 +339,7 @@ public class ConfigBuilderFragment extends SubscriberFragment {
} }
void onEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) { public static void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
ArrayList<PluginBase> pluginsInCategory = null; ArrayList<PluginBase> pluginsInCategory = null;
switch (type) { switch (type) {
// Multiple selection allowed // Multiple selection allowed
@ -391,10 +391,14 @@ public class ConfigBuilderFragment extends SubscriberFragment {
else else
pluginsInCategory.get(0).setPluginEnabled(type, true); pluginsInCategory.get(0).setPluginEnabled(type, true);
} }
updateGUI();
} }
} }
void onEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
processOnEnabledCategoryChanged(changedPlugin, type);
updateGUI();
}
/**** /****
* Method for Setting the Height of the ListView dynamically. * Method for Setting the Height of the ListView dynamically.
* *** Hack to fix the issue of not showing all the items of the ListView * *** Hack to fix the issue of not showing all the items of the ListView

View file

@ -67,24 +67,20 @@ public class ObjectivesFragment extends SubscriberFragment {
holder.startButton.setTag(o); holder.startButton.setTag(o);
holder.verifyButton.setTag(o); holder.verifyButton.setTag(o);
holder.startButton.setOnClickListener(new View.OnClickListener() { holder.startButton.setOnClickListener(v -> {
public void onClick(View v) { ObjectivesPlugin.Objective o1 = (ObjectivesPlugin.Objective) v.getTag();
ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag(); o1.started = new Date();
o.started = new Date(); updateGUI();
ObjectivesPlugin.saveProgress();
});
holder.verifyButton.setOnClickListener(v -> {
ObjectivesPlugin.Objective o12 = (ObjectivesPlugin.Objective) v.getTag();
if (ObjectivesPlugin.getPlugin().requirementsMet(o12.num).done || enableFake.isChecked()) {
o12.accomplished = new Date();
updateGUI(); updateGUI();
ObjectivesPlugin.saveProgress(); ObjectivesPlugin.saveProgress();
} }
}); });
holder.verifyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag();
if (ObjectivesPlugin.getPlugin().requirementsMet(o.num).done || enableFake.isChecked()) {
o.accomplished = new Date();
updateGUI();
ObjectivesPlugin.saveProgress();
}
}
});
long prevObjectiveAccomplishedTime = position > 0 ? long prevObjectiveAccomplishedTime = position > 0 ?
objectives.get(position - 1).accomplished.getTime() : -1; objectives.get(position - 1).accomplished.getTime() : -1;

View file

@ -22,6 +22,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
@ -87,7 +88,7 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
this.started = started; this.started = started;
} }
boolean isStarted() { public boolean isStarted() {
return started.getTime() > 0; return started.getTime() > 0;
} }
@ -233,6 +234,7 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
editor.apply(); editor.apply();
if (Config.logPrefsChange) if (Config.logPrefsChange)
log.debug("Objectives stored"); log.debug("Objectives stored");
MainApp.bus().post(new EventObjectivesSaved());
} }
} }

View file

@ -0,0 +1,6 @@
package info.nightscout.androidaps.plugins.ConstraintsObjectives.events;
import info.nightscout.androidaps.events.Event;
public class EventObjectivesSaved extends Event {
}

View file

@ -981,16 +981,19 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (timeView != null) { //must not exists if (timeView != null) { //must not exists
timeView.setText(DateUtil.timeString(new Date())); timeView.setText(DateUtil.timeString(new Date()));
} }
updateNotifications();
pumpStatusLayout.setVisibility(View.GONE);
loopStatusLayout.setVisibility(View.GONE);
if (!MainApp.getConfigBuilder().isProfileValid("Overview")) { if (!MainApp.getConfigBuilder().isProfileValid("Overview")) {
pumpStatusView.setText(R.string.noprofileset); pumpStatusView.setText(R.string.noprofileset);
pumpStatusLayout.setVisibility(View.VISIBLE); pumpStatusLayout.setVisibility(View.VISIBLE);
loopStatusLayout.setVisibility(View.GONE);
return; return;
} }
pumpStatusLayout.setVisibility(View.GONE);
loopStatusLayout.setVisibility(View.VISIBLE); loopStatusLayout.setVisibility(View.VISIBLE);
updateNotifications();
CareportalFragment.updateAge(getActivity(), sage, iage, cage, pbage); CareportalFragment.updateAge(getActivity(), sage, iage, cage, pbage);
BgReading actualBG = DatabaseHelper.actualBg(); BgReading actualBG = DatabaseHelper.actualBg();
BgReading lastBG = DatabaseHelper.lastBg(); BgReading lastBG = DatabaseHelper.lastBg();

View file

@ -60,6 +60,10 @@ public class Notification {
public static final int PROFILE_SWITCH_MISSING = 32; public static final int PROFILE_SWITCH_MISSING = 32;
public static final int NOT_ENG_MODE_OR_RELEASE = 33; public static final int NOT_ENG_MODE_OR_RELEASE = 33;
public static final int WRONG_PUMP_PASSWORD = 34; public static final int WRONG_PUMP_PASSWORD = 34;
public static final int PERMISSION_STORAGE = 35;
public static final int PERMISSION_LOCATION = 36;
public static final int PERMISSION_BATTERY = 37;
public static final int PERMISSION_SMS = 38;
public int id; public int id;

View file

@ -42,9 +42,12 @@ public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter<Notifi
public void onBindViewHolder(NotificationsViewHolder holder, int position) { public void onBindViewHolder(NotificationsViewHolder holder, int position) {
Notification notification = notificationsList.get(position); Notification notification = notificationsList.get(position);
holder.dismiss.setTag(notification); holder.dismiss.setTag(notification);
if (Objects.equals(notification.text, MainApp.gs(R.string.nsalarm_staledata))) if (notification instanceof NotificationWithAction)
holder.dismiss.setText(((NotificationWithAction) notification).buttonText);
else if (Objects.equals(notification.text, MainApp.gs(R.string.nsalarm_staledata)))
holder.dismiss.setText("snooze"); holder.dismiss.setText("snooze");
holder.text.setText(notification.text+'\n');
holder.text.setText(notification.text + '\n');
holder.time.setText(DateUtil.timeString(notification.date)); holder.time.setText(DateUtil.timeString(notification.date));
if (notification.level == Notification.URGENT) if (notification.level == Notification.URGENT)
holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationUrgent)); holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationUrgent));
@ -100,6 +103,9 @@ public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter<Notifi
log.debug("snooze nsalarm_staledatavalue in minutes is " + SP.getInt("nsalarm_staledatavalue", 15) + "\n in ms is: " + msToSnooze + " currentTimeMillis is: " + System.currentTimeMillis()); log.debug("snooze nsalarm_staledatavalue in minutes is " + SP.getInt("nsalarm_staledatavalue", 15) + "\n in ms is: " + msToSnooze + " currentTimeMillis is: " + System.currentTimeMillis());
nstore.snoozeTo(System.currentTimeMillis() + (SP.getInt("nsalarm_staledatavalue", 15) * 60 * 1000L)); nstore.snoozeTo(System.currentTimeMillis() + (SP.getInt("nsalarm_staledatavalue", 15) * 60 * 1000L));
} }
if (notification instanceof NotificationWithAction) {
((NotificationWithAction) notification).action.run();
}
break; break;
} }
} }

View file

@ -61,7 +61,7 @@ public class NotificationStore {
} }
store.add(n); store.add(n);
if (SP.getBoolean(MainApp.gs(R.string.key_raise_notifications_as_android_notifications), false)) { if (SP.getBoolean(MainApp.gs(R.string.key_raise_notifications_as_android_notifications), false) && !(n instanceof NotificationWithAction)) {
raiseSystemNotification(n); raiseSystemNotification(n);
if (usesChannels && n.soundId != null) { if (usesChannels && n.soundId != null) {
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);

View file

@ -0,0 +1,16 @@
package info.nightscout.androidaps.plugins.Overview.notifications;
public class NotificationWithAction extends Notification {
Runnable action;
String buttonText;
public NotificationWithAction(int id, String text, int level) {
super(id, text, level);
}
public void action(String buttonText, Runnable action) {
this.buttonText = buttonText;
this.action = action;
}
}

View file

@ -4,7 +4,6 @@ package info.nightscout.androidaps.plugins.ProfileLocal;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -23,7 +22,6 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
@ -109,34 +107,25 @@ public class LocalProfileFragment extends SubscriberFragment {
mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl); mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol); mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
mgdlView.setOnClickListener(new View.OnClickListener() { mgdlView.setOnClickListener(v -> {
@Override LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
public void onClick(View v) { LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl;
LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked(); mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl; doEdit();
mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
doEdit();
}
}); });
mmolView.setOnClickListener(new View.OnClickListener() { mmolView.setOnClickListener(v -> {
@Override LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked();
public void onClick(View v) { LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol;
LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked(); mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol; doEdit();
mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
doEdit();
}
}); });
profileswitchButton.setOnClickListener(new View.OnClickListener() { profileswitchButton.setOnClickListener(view -> {
@Override NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
public void onClick(View view) { final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); profileswitch.executeProfileSwitch = true;
final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT; newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
profileswitch.executeProfileSwitch = true; newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
}
}); });
resetButton.setOnClickListener(view -> { resetButton.setOnClickListener(view -> {

View file

@ -13,6 +13,7 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
@ -81,6 +82,7 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface {
edited = false; edited = false;
if (Config.logPrefsChange) if (Config.logPrefsChange)
log.debug("Storing settings: " + getRawProfile().getData().toString()); log.debug("Storing settings: " + getRawProfile().getData().toString());
MainApp.bus().post(new EventProfileStoreChanged());
} }
public synchronized void loadSettings() { public synchronized void loadSettings() {

View file

@ -16,6 +16,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
@ -43,7 +44,7 @@ public class NSProfilePlugin extends PluginBase implements ProfileInterface {
super(new PluginDescription() super(new PluginDescription()
.mainType(PluginType.PROFILE) .mainType(PluginType.PROFILE)
.fragmentClass(NSProfileFragment.class.getName()) .fragmentClass(NSProfileFragment.class.getName())
.pluginName(R.string.profileviewer) .pluginName(R.string.nsprofile)
.shortName(R.string.profileviewer_shortname) .shortName(R.string.profileviewer_shortname)
.alwaysEnabled(Config.NSCLIENT) .alwaysEnabled(Config.NSCLIENT)
.alwayVisible(Config.NSCLIENT) .alwayVisible(Config.NSCLIENT)
@ -68,6 +69,7 @@ public class NSProfilePlugin extends PluginBase implements ProfileInterface {
profile = new ProfileStore(newProfile.getData()); profile = new ProfileStore(newProfile.getData());
storeNSProfile(); storeNSProfile();
MainApp.bus().post(new EventNSProfileUpdateGUI()); MainApp.bus().post(new EventNSProfileUpdateGUI());
MainApp.bus().post(new EventProfileStoreChanged());
} }
private void storeNSProfile() { private void storeNSProfile() {

View file

@ -73,34 +73,25 @@ public class SimpleProfileFragment extends SubscriberFragment {
targetlowView.setText(SimpleProfilePlugin.getPlugin().targetLow.toString()); targetlowView.setText(SimpleProfilePlugin.getPlugin().targetLow.toString());
targethighView.setText(SimpleProfilePlugin.getPlugin().targetHigh.toString()); targethighView.setText(SimpleProfilePlugin.getPlugin().targetHigh.toString());
mgdlView.setOnClickListener(new View.OnClickListener() { mgdlView.setOnClickListener(v -> {
@Override SimpleProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
public void onClick(View v) { SimpleProfilePlugin.getPlugin().mmol = !SimpleProfilePlugin.getPlugin().mgdl;
SimpleProfilePlugin.getPlugin().mgdl = mgdlView.isChecked(); mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol);
SimpleProfilePlugin.getPlugin().mmol = !SimpleProfilePlugin.getPlugin().mgdl; SimpleProfilePlugin.getPlugin().storeSettings();
mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol);
SimpleProfilePlugin.getPlugin().storeSettings();
}
}); });
mmolView.setOnClickListener(new View.OnClickListener() { mmolView.setOnClickListener(v -> {
@Override SimpleProfilePlugin.getPlugin().mmol = mmolView.isChecked();
public void onClick(View v) { SimpleProfilePlugin.getPlugin().mgdl = !SimpleProfilePlugin.getPlugin().mmol;
SimpleProfilePlugin.getPlugin().mmol = mmolView.isChecked(); mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl);
SimpleProfilePlugin.getPlugin().mgdl = !SimpleProfilePlugin.getPlugin().mmol; SimpleProfilePlugin.getPlugin().storeSettings();
mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl);
SimpleProfilePlugin.getPlugin().storeSettings();
}
}); });
profileswitchButton.setOnClickListener(new View.OnClickListener() { profileswitchButton.setOnClickListener(view -> {
@Override NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
public void onClick(View view) { final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); profileswitch.executeProfileSwitch = true;
final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH; newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
profileswitch.executeProfileSwitch = true; newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
}
}); });
TextWatcher textWatch = new TextWatcher() { TextWatcher textWatch = new TextWatcher() {
@ -152,20 +143,17 @@ public class SimpleProfileFragment extends SubscriberFragment {
protected void updateGUI() { protected void updateGUI() {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(() -> {
@Override boolean isValid = SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile));
public void run() { if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) {
boolean isValid = SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile)); profileswitchButton.setVisibility(View.GONE);
if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) { } else {
profileswitchButton.setVisibility(View.GONE); profileswitchButton.setVisibility(View.VISIBLE);
} else {
profileswitchButton.setVisibility(View.VISIBLE);
}
if (isValid)
invalidProfile.setVisibility(View.GONE);
else
invalidProfile.setVisibility(View.VISIBLE);
} }
if (isValid)
invalidProfile.setVisibility(View.GONE);
else
invalidProfile.setVisibility(View.VISIBLE);
}); });
} }

View file

@ -14,6 +14,7 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
@ -73,6 +74,7 @@ public class SimpleProfilePlugin extends PluginBase implements ProfileInterface
createConvertedProfile(); createConvertedProfile();
if (Config.logPrefsChange) if (Config.logPrefsChange)
log.debug("Storing settings: " + getRawProfile().getData().toString()); log.debug("Storing settings: " + getRawProfile().getData().toString());
MainApp.bus().post(new EventProfileStoreChanged());
} }
private void loadSettings() { private void loadSettings() {

View file

@ -62,13 +62,15 @@ public class BLEScanActivity extends AppCompatActivity {
super.onResume(); super.onResume();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); if (mBluetoothAdapter != null) {
if (mBluetoothLeScanner == null) {
mBluetoothAdapter.enable();
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
if (mBluetoothLeScanner == null) {
mBluetoothAdapter.enable();
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
startScan();
} }
startScan();
} }
@Override @Override
@ -79,11 +81,13 @@ public class BLEScanActivity extends AppCompatActivity {
} }
private void startScan() { private void startScan() {
mBluetoothLeScanner.startScan(mBleScanCallback); if (mBluetoothLeScanner != null)
mBluetoothLeScanner.startScan(mBleScanCallback);
} }
private void stopScan() { private void stopScan() {
mBluetoothLeScanner.stopScan(mBleScanCallback); if (mBluetoothLeScanner != null)
mBluetoothLeScanner.stopScan(mBleScanCallback);
} }
private void addBleDevice(BluetoothDevice device) { private void addBleDevice(BluetoothDevice device) {

View file

@ -0,0 +1,432 @@
package info.nightscout.androidaps.setupwizard;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.PreferencesActivity;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
import info.nightscout.androidaps.setupwizard.elements.SWBreak;
import info.nightscout.androidaps.setupwizard.elements.SWButton;
import info.nightscout.androidaps.setupwizard.elements.SWFragment;
import info.nightscout.androidaps.setupwizard.elements.SWHtmlLink;
import info.nightscout.androidaps.setupwizard.elements.SWInfotext;
import info.nightscout.androidaps.setupwizard.elements.SWPlugin;
import info.nightscout.androidaps.setupwizard.elements.SWRadioButton;
import info.nightscout.androidaps.setupwizard.elements.SWEditString;
import info.nightscout.androidaps.setupwizard.elements.SWEditUrl;
import info.nightscout.androidaps.setupwizard.events.EventSWLabel;
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
import info.nightscout.utils.AndroidPermission;
import info.nightscout.utils.ImportExportPrefs;
import info.nightscout.utils.LocaleHelper;
import info.nightscout.utils.PasswordProtection;
import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
public class SWDefinition {
private static Logger log = LoggerFactory.getLogger(SWDefinition.class);
private String packageName;
private AppCompatActivity activity;
private List<SWScreen> screens = new ArrayList<>();
public void setActivity(AppCompatActivity activity) {
this.activity = activity;
packageName = activity.getPackageName();
}
public AppCompatActivity getActivity() {
return activity;
}
public List<SWScreen> getScreens() {
return screens;
}
SWDefinition add(SWScreen newScreen) {
screens.add(newScreen);
return this;
}
SWDefinition() {
// List all the screens here
add(new SWScreen(R.string.nav_setupwizard)
.add(new SWInfotext()
.label(R.string.welcometosetupwizard))
.add(new SWButton()
.text(R.string.nav_import)
.action(() -> ImportExportPrefs.importSharedPreferences(getActivity()))
.visibility(ImportExportPrefs.file::exists))
.add(new SWInfotext()
.label(R.string.backupismissing)
.visibility(() -> !ImportExportPrefs.file.exists()))
)
.add(new SWScreen(R.string.language)
.skippable(false)
.add(new SWRadioButton()
.option(R.array.languagesArray, R.array.languagesValues)
.preferenceId(R.string.key_language).label(R.string.language)
.comment(R.string.setupwizard_language_prompt))
.validator(() -> {
String lang = SP.getString("language", "en");
LocaleHelper.setLocale(MainApp.instance().getApplicationContext(), lang);
return SP.contains(R.string.key_language);
})
)
.add(new SWScreen(R.string.end_user_license_agreement)
.skippable(false)
.add(new SWInfotext()
.label(R.string.end_user_license_agreement_text))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.end_user_license_agreement_i_understand)
.visibility(() -> !SP.getBoolean(R.string.key_i_understand, false))
.action(() -> {
SP.putBoolean(R.string.key_i_understand, true);
MainApp.bus().post(new EventSWUpdate(false));
}))
.visibility(() -> !SP.getBoolean(R.string.key_i_understand, false))
.validator(() -> SP.getBoolean(R.string.key_i_understand, false))
)
.add(new SWScreen(R.string.permission)
.skippable(false)
.add(new SWInfotext()
.label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name))))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.askforpermission)
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
.action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY)))
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
.validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)))
)
.add(new SWScreen(R.string.permission)
.skippable(false)
.add(new SWInfotext()
.label(MainApp.gs(R.string.needlocationpermission)))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.askforpermission)
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION))
.action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION)))
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION))
.validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)))
)
.add(new SWScreen(R.string.permission)
.skippable(false)
.add(new SWInfotext()
.label(MainApp.gs(R.string.needstoragepermission)))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.askforpermission)
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
.action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE)))
.visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
.validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
)
.add(new SWScreen(R.string.nsclientinternal_title)
.skippable(true)
.add(new SWInfotext()
.label(R.string.nsclientinfotext))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.enable_nsclient)
.action(() -> {
NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true);
NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true);
ConfigBuilderFragment.processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL);
ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
MainApp.bus().post(new EventConfigBuilderChange());
MainApp.bus().post(new EventSWUpdate(true));
})
.visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL)))
.add(new SWEditUrl()
.preferenceId(R.string.key_nsclientinternal_url)
.label(R.string.nsclientinternal_url_title)
.comment(R.string.nsclientinternal_url_dialogmessage))
.add(new SWEditString()
.validator(text -> text.length() >= 12)
.preferenceId(R.string.key_nsclientinternal_api_secret)
.label(R.string.nsclientinternal_secret_dialogtitle)
.comment(R.string.nsclientinternal_secret_dialogmessage))
.add(new SWBreak())
.add(new SWEventListener(this)
.label(R.string.status)
.initialStatus(NSClientPlugin.getPlugin().status)
.listener(new Object() {
@Subscribe
public void onEventNSClientStatus(EventNSClientStatus event) {
MainApp.bus().post(new EventSWLabel(event.status));
}
})
)
.add(new SWBreak())
.validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)
.visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth))
)
.add(new SWScreen(R.string.patientage)
.skippable(false)
.add(new SWInfotext()
.label(R.string.patientage_summary))
.add(new SWBreak())
.add(new SWRadioButton()
.option(R.array.ageArray, R.array.ageValues)
.preferenceId(R.string.key_age)
.label(R.string.patientage)
.comment(R.string.patientage_summary))
.validator(() -> SP.contains(R.string.key_age))
)
.add(new SWScreen(R.string.configbuilder_insulin)
.skippable(false)
.add(new SWInfotext()
.label(MainApp.gs(R.string.fastactinginsulincomment) + " = " + MainApp.gs(R.string.rapid_acting_oref)))
.add(new SWInfotext()
.label(MainApp.gs(R.string.ultrafastactinginsulincomment) + " = " + MainApp.gs(R.string.ultrarapid_oref)))
.add(new SWInfotext()
.label(MainApp.gs(R.string.free_peak_oref_description) + " = " + MainApp.gs(R.string.free_peak_oref)))
.add(new SWBreak())
.add(new SWInfotext()
.label(R.string.diawarning))
.add(new SWBreak())
.add(new SWPlugin()
.option(PluginType.INSULIN)
.label(R.string.configbuilder_insulin))
.validator(() -> MainApp.getConfigBuilder().getActiveInsulin() != null)
)
.add(new SWScreen(R.string.configbuilder_bgsource)
.skippable(false)
.add(new SWInfotext()
.label(R.string.setupwizard_bgsource_description))
.add(new SWPlugin()
.option(PluginType.BGSOURCE)
.label(R.string.configbuilder_bgsource))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.bgsourcesetup)
.action(() -> {
final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveBgSource();
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(activity, PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
activity.startActivity(i);
}, null);
})
.visibility(() -> MainApp.getConfigBuilder().getActiveBgSource()!= null && ((PluginBase) MainApp.getConfigBuilder().getActiveBgSource()).getPreferencesId() > 0))
.validator(() -> MainApp.getConfigBuilder().getActiveBgSource() != null)
)
.add(new SWScreen(R.string.configbuilder_profile)
.skippable(false)
.add(new SWInfotext()
.label(R.string.setupwizard_profile_description))
.add(new SWBreak())
.add(new SWPlugin()
.option(PluginType.PROFILE)
.label(R.string.configbuilder_profile))
.validator(() -> MainApp.getConfigBuilder().getActiveProfileInterface() != null)
)
.add(new SWScreen(R.string.nsprofile)
.skippable(false)
.add(new SWInfotext()
.label(R.string.adjustprofileinns))
.add(new SWFragment(this)
.add(new NSProfileFragment()))
.validator(() -> NSProfilePlugin.getPlugin().getProfile() != null && NSProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard"))
.visibility(() -> NSProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE))
)
.add(new SWScreen(R.string.localprofile)
.skippable(false)
.add(new SWFragment(this)
.add(new LocalProfileFragment()))
.validator(() -> LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard"))
.visibility(() -> LocalProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE))
)
.add(new SWScreen(R.string.simpleprofile)
.skippable(false)
.add(new SWFragment(this)
.add(new SimpleProfileFragment()))
.validator(() -> SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard"))
.visibility(() -> SimpleProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE))
)
.add(new SWScreen(R.string.profileswitch)
.skippable(false)
.add(new SWInfotext()
.label(R.string.profileswitch_ismissing))
.add(new SWButton()
.text(R.string.profileswitch)
.action(() -> {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getActivity().getSupportFragmentManager(), "NewNSTreatmentDialog");
}))
.validator(() -> MainApp.getConfigBuilder().getProfile() != null)
.visibility(() -> MainApp.getConfigBuilder().getProfile() == null)
)
.add(new SWScreen(R.string.configbuilder_pump)
.skippable(false)
.add(new SWPlugin()
.option(PluginType.PUMP)
.label(R.string.configbuilder_pump))
.add(new SWButton()
.text(R.string.pumpsetup)
.action(() -> {
final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActivePump();
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(activity, PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
activity.startActivity(i);
}, null);
})
.visibility(() -> ((PluginBase) MainApp.getConfigBuilder().getActivePump()).getPreferencesId() > 0))
.add(new SWButton()
.text(R.string.readstatus)
.action(() -> ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null))
.visibility(() -> MainApp.getConfigBuilder().getActivePump() != null))
.add(new SWEventListener(this)
.listener(new Object() {
@Subscribe
public void onEventPumpStatusChanged(EventPumpStatusChanged event) {
MainApp.bus().post(new EventSWLabel(event.textStatus()));
}
})
)
.validator(() -> MainApp.getConfigBuilder().getActivePump() != null && MainApp.getConfigBuilder().getActivePump().isInitialized())
)
.add(new SWScreen(R.string.configbuilder_aps)
.skippable(false)
.add(new SWInfotext()
.label(R.string.setupwizard_aps_description))
.add(new SWBreak())
.add(new SWHtmlLink()
.label("https://openaps.readthedocs.io/en/latest/"))
.add(new SWBreak())
.add(new SWPlugin()
.option(PluginType.APS)
.label(R.string.configbuilder_aps))
.add(new SWButton()
.text(R.string.apssetup)
.action(() -> {
final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveAPS();
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(activity, PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
activity.startActivity(i);
}, null);
})
.visibility(() -> MainApp.getConfigBuilder().getActiveAPS() != null && ((PluginBase) MainApp.getConfigBuilder().getActiveAPS()).getPreferencesId() > 0))
.validator(() -> MainApp.getConfigBuilder().getActiveAPS() != null)
)
.add(new SWScreen(R.string.configbuilder_loop)
.skippable(false)
.add(new SWInfotext()
.label(R.string.setupwizard_loop_description))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.enableloop)
.action(() -> {
LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true);
LoopPlugin.getPlugin().setFragmentVisible(PluginType.LOOP, true);
ConfigBuilderFragment.processOnEnabledCategoryChanged(LoopPlugin.getPlugin(), PluginType.LOOP);
ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
MainApp.bus().post(new EventConfigBuilderChange());
MainApp.bus().post(new EventSWUpdate(true));
})
.visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)))
.validator(() -> LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
.visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
)
.add(new SWScreen(R.string.configbuilder_sensitivity)
.skippable(false)
.add(new SWInfotext()
.label(R.string.setupwizard_sensitivity_description))
.add(new SWHtmlLink()
.label(R.string.setupwizard_sensitivity_url))
.add(new SWBreak())
.add(new SWPlugin()
.option(PluginType.SENSITIVITY)
.label(R.string.configbuilder_sensitivity))
.add(new SWBreak())
.add(new SWButton()
.text(R.string.sensitivitysetup)
.action(() -> {
final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveSensitivity();
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(activity, PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
activity.startActivity(i);
}, null);
})
.visibility(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null && ((PluginBase) MainApp.getConfigBuilder().getActiveSensitivity()).getPreferencesId() > 0))
.validator(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null)
)
.add(new SWScreen(R.string.objectives)
.skippable(false)
.add(new SWInfotext()
.label(R.string.setupwizard_objectives_description))
.add(new SWButton()
.text(R.string.enableobjectives)
.action(() -> {
ObjectivesPlugin.getPlugin().setPluginEnabled(PluginType.CONSTRAINTS, true);
ObjectivesPlugin.getPlugin().setFragmentVisible(PluginType.CONSTRAINTS, true);
ConfigBuilderFragment.processOnEnabledCategoryChanged(ObjectivesPlugin.getPlugin(), PluginType.CONSTRAINTS);
ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
MainApp.bus().post(new EventConfigBuilderChange());
MainApp.bus().post(new EventSWUpdate(true));
})
.visibility(() -> !ObjectivesPlugin.getPlugin().isFragmentVisible()))
.validator(() -> ObjectivesPlugin.getPlugin().isEnabled(PluginType.CONSTRAINTS))
.visibility(() -> !ObjectivesPlugin.getPlugin().isFragmentVisible())
)
.add(new SWScreen(R.string.objectives)
.skippable(false)
.add(new SWInfotext()
.label(R.string.startobjective))
.add(new SWBreak())
.add(new SWFragment(this)
.add(new ObjectivesFragment()))
.validator(() -> ObjectivesPlugin.getPlugin().objectives.get(0).isStarted())
.visibility(() -> !ObjectivesPlugin.getPlugin().objectives.get(0).isStarted())
)
;
}
}

View file

@ -0,0 +1,72 @@
package info.nightscout.androidaps.setupwizard;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.setupwizard.elements.SWItem;
import info.nightscout.androidaps.setupwizard.events.EventSWLabel;
public class SWEventListener extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWEventListener.class);
private int textLabel = 0;
private String status = "";
TextView textView;
Object listener;
SWDefinition definition;
SWEventListener(SWDefinition definition) {
super(Type.LISTENER);
this.definition = definition;
MainApp.bus().register(this);
}
public SWEventListener label(int newLabel) {
this.textLabel = newLabel;
return this;
}
public SWEventListener initialStatus(String status) {
this.status = status;
return this;
}
public SWEventListener listener(Object listener) {
this.listener = listener;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
textView = new TextView(context);
textView.setId(view.generateViewId());
textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status);
layout.addView(textView);
if (listener != null)
try {
MainApp.bus().register(listener);
} catch (Exception ignored) {}
}
@Subscribe
public void onEventSWLabel(final EventSWLabel l) {
status = l.label;
if (definition != null && definition.getActivity() != null)
definition.getActivity().runOnUiThread(() -> {
if (textView != null)
textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status);
});
}
}

View file

@ -0,0 +1,49 @@
package info.nightscout.androidaps.setupwizard;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.setupwizard.elements.SWItem;
public class SWScreen {
int header;
List<SWItem> items = new ArrayList<>();
SWValidator validator;
SWValidator visibility;
boolean skippable = false;
public SWScreen(int header) {
this.header = header;
}
public String getHeader() {
return MainApp.gs(header);
}
public SWScreen skippable(boolean skippable) {
this.skippable = skippable;
return this;
}
public SWScreen add(SWItem newItem) {
items.add(newItem);
return this;
}
public SWScreen validator(SWValidator validator) {
this.validator = validator;
return this;
}
public SWScreen visibility(SWValidator visibility) {
this.visibility = visibility;
return this;
}
public void processVisibility() {
for (SWItem i : items)
i.processVisibility();
}
}

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.setupwizard;
public interface SWTextValidator {
boolean isValid(String text);
}

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.setupwizard;
public interface SWValidator {
boolean isValid();
}

View file

@ -0,0 +1,220 @@
package info.nightscout.androidaps.setupwizard;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.events.EventProfileSwitchChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.setupwizard.elements.SWItem;
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
import info.nightscout.utils.AndroidPermission;
import info.nightscout.utils.LocaleHelper;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.SP;
public class SetupWizardActivity extends AppCompatActivity {
//logging
private static Logger log = LoggerFactory.getLogger(SetupWizardActivity.class);
private SWDefinition swDefinition = new SWDefinition();
private List<SWScreen> screens = swDefinition.getScreens();
private int currentWizardPage = 0;
public static final String INTENT_MESSAGE = "WIZZARDPAGE";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocaleHelper.onCreate(this, "en");
setContentView(R.layout.activity_setupwizard);
Intent intent = getIntent();
currentWizardPage = intent.getIntExtra(SetupWizardActivity.INTENT_MESSAGE, 0);
if (screens.size() > 0 && currentWizardPage < screens.size()) {
SWScreen currentScreen = screens.get(currentWizardPage);
//Set screen name
TextView screenName = (TextView) findViewById(R.id.sw_content);
screenName.setText(currentScreen.getHeader());
swDefinition.setActivity(this);
//Generate layout first
generateLayout();
updateButtons();
}
}
@Override
public void onBackPressed() {
if (currentWizardPage == 0) OKDialog.showConfirmation(this, MainApp.gs(R.string.exitwizard), this::finish);
else showPreviousPage(null);
}
public void exitPressed(View view) {
SP.putBoolean(R.string.key_setupwizard_processed, true);
OKDialog.showConfirmation(this, MainApp.gs(R.string.exitwizard), this::finish);
}
@Override
public void onPause() {
super.onPause();
MainApp.bus().unregister(this);
}
@Override
protected void onResume() {
super.onResume();
MainApp.bus().register(this);
swDefinition.setActivity(this);
}
@Subscribe
public void onContentUpdate(EventSWUpdate ev) {
if (ev.redraw)
generateLayout();
updateButtons();
}
@Subscribe
public void onEventNSClientStatus(EventNSClientStatus ignored) {
updateButtons();
}
@Subscribe
public void onEventPumpStatusChanged(EventPumpStatusChanged ignored) {
updateButtons();
}
@Subscribe
public void onEventProfileStoreChanged(EventProfileStoreChanged ignored) {
updateButtons();
}
@Subscribe
public void onEventProfileSwitchChange(EventProfileSwitchChange ignored) {
updateButtons();
}
@Subscribe
public void onEventObjectivesSaved(EventObjectivesSaved ignored) {
updateButtons();
}
private void generateLayout() {
SWScreen currentScreen = screens.get(currentWizardPage);
LinearLayout layout = SWItem.generateLayout(this.findViewById(R.id.sw_content_fields));
for (int i = 0; i < currentScreen.items.size(); i++) {
SWItem currentItem = currentScreen.items.get(i);
currentItem.generateDialog(this.findViewById(R.id.sw_content_fields), layout);
}
}
private void updateButtons() {
runOnUiThread(() -> {
SWScreen currentScreen = screens.get(currentWizardPage);
if (currentScreen.validator == null || currentScreen.validator.isValid() || currentScreen.skippable) {
if (currentWizardPage == nextPage()) {
findViewById(R.id.finish_button).setVisibility(View.VISIBLE);
findViewById(R.id.next_button).setVisibility(View.GONE);
} else {
findViewById(R.id.finish_button).setVisibility(View.GONE);
findViewById(R.id.next_button).setVisibility(View.VISIBLE);
}
} else {
findViewById(R.id.finish_button).setVisibility(View.GONE);
findViewById(R.id.next_button).setVisibility(View.GONE);
}
if (currentWizardPage == 0)
findViewById(R.id.previous_button).setVisibility(View.GONE);
else
findViewById(R.id.previous_button).setVisibility(View.VISIBLE);
currentScreen.processVisibility();
});
}
public void showNextPage(View view) {
this.finish();
Intent intent = new Intent(this, SetupWizardActivity.class);
intent.putExtra(INTENT_MESSAGE, nextPage());
startActivity(intent);
}
public void showPreviousPage(View view) {
this.finish();
Intent intent = new Intent(this, SetupWizardActivity.class);
intent.putExtra(INTENT_MESSAGE, previousPage());
startActivity(intent);
}
// Go back to overview
public void finishSetupWizard(View view) {
SP.putBoolean(R.string.key_setupwizard_processed, true);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
private int nextPage() {
int page = currentWizardPage + 1;
while (page < screens.size()) {
if (screens.get(page).visibility == null || screens.get(page).visibility.isValid())
return page;
page++;
}
return currentWizardPage;
}
private int previousPage() {
int page = currentWizardPage - 1;
while (page > 0) {
if (screens.get(page).visibility == null || screens.get(page).visibility.isValid())
return page;
page--;
}
return currentWizardPage;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length != 0) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
switch (requestCode) {
case AndroidPermission.CASE_STORAGE:
//show dialog after permission is granted
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setMessage(R.string.alert_dialog_storage_permission_text);
alert.setPositiveButton(R.string.ok, null);
alert.show();
break;
case AndroidPermission.CASE_LOCATION:
case AndroidPermission.CASE_SMS:
case AndroidPermission.CASE_BATTERY:
break;
}
}
}
updateButtons();
}
}

View file

@ -0,0 +1,47 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.setupwizard.SWValidator;
public class SWBreak extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWBreak.class);
private TextView l;
private SWValidator visibilityValidator;
public SWBreak() {
super(Type.TEXT);
}
public SWBreak visibility(SWValidator visibilityValidator) {
this.visibilityValidator = visibilityValidator;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
l = new TextView(context);
l.setId(View.generateViewId());
l.setText("\n");
layout.addView(l);
}
@Override
public void processVisibility() {
if (visibilityValidator != null && !visibilityValidator.isValid())
l.setVisibility(View.GONE);
else
l.setVisibility(View.VISIBLE);
}
}

View file

@ -0,0 +1,63 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.setupwizard.SWValidator;
public class SWButton extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWButton.class);
private Runnable buttonRunnable;
private int buttonText;
private SWValidator buttonValidator;
private Button button;
public SWButton() {
super(Type.BUTTON);
}
public SWButton text(int buttonText) {
this.buttonText = buttonText;
return this;
}
public SWButton action(Runnable buttonRunnable) {
this.buttonRunnable = buttonRunnable;
return this;
}
public SWButton visibility(SWValidator buttonValidator) {
this.buttonValidator = buttonValidator;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
button = new Button(context);
button.setText(buttonText);
button.setOnClickListener((v) -> {
if (buttonRunnable != null)
buttonRunnable.run();
});
processVisibility();
layout.addView(button);
super.generateDialog(view, layout);
}
@Override
public void processVisibility() {
if (buttonValidator != null && !buttonValidator.isValid())
button.setVisibility(View.GONE);
else
button.setVisibility(View.VISIBLE);
}
}

View file

@ -0,0 +1,76 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.CheckBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.utils.SP;
/**
* Created by Rumen Georgiev on 5/9/2018.
*/
public class SWCheckbox extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWCheckbox.class);
int labelsArray;
int valuesArray;
String label = "";
int preferenceID;
private CheckBox checkBox;
public SWCheckbox() {
super(Type.CHECKBOX);
}
public SWCheckbox option(String label, int preferenceID) {
this.label = label;
this.preferenceID = preferenceID;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
// Get if there is already value in SP
Boolean previousValue;
previousValue = SP.getBoolean(preferenceId, false);
checkBox = new CheckBox(context);
checkBox.setText(label);
checkBox.setChecked(previousValue);
checkBox.setVisibility(View.VISIBLE);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
ArrayList<PluginBase> pluginsInCategory;
pluginsInCategory = MainApp.getSpecificPluginsList(PluginType.PUMP);
PluginBase found = null;
for (PluginBase p : pluginsInCategory) {
if (p.isEnabled(PluginType.PUMP) && found == null) {
found = p;
} else if (p.isEnabled(PluginType.PUMP)) {
// set others disabled
p.setPluginEnabled(PluginType.PUMP, false);
}
}
log.debug("Enabled pump plugin:"+found.getClass());
save(checkBox.isChecked());
}
});
layout.addView(checkBox);
super.generateDialog(view, layout);
}
public void save(boolean value){
SP.putBoolean(preferenceID, value);
}
}

View file

@ -0,0 +1,79 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.graphics.Typeface;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.setupwizard.SWTextValidator;
import info.nightscout.utils.SP;
public class SWEditString extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWEditString.class);
private SWTextValidator validator = null;
public SWEditString() {
super(Type.STRING);
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
TextView l = new TextView(context);
l.setId(view.generateViewId());
l.setText(label);
l.setTypeface(l.getTypeface(), Typeface.BOLD);
layout.addView(l);
TextView c = new TextView(context);
c.setId(view.generateViewId());
c.setText(comment);
c.setTypeface(c.getTypeface(), Typeface.ITALIC);
layout.addView(c);
EditText editText = new EditText(context);
editText.setId(view.generateViewId());
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setMaxLines(1);
editText.setText(SP.getString(preferenceId, ""));
layout.addView(editText);
super.generateDialog(view, layout);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (validator != null && validator.isValid(s.toString()))
save(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
public SWEditString preferenceId(int preferenceId) {
this.preferenceId = preferenceId;
return this;
}
public SWEditString validator(SWTextValidator validator) {
this.validator = validator;
return this;
}
}

View file

@ -0,0 +1,77 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.graphics.Typeface;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Patterns;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.setupwizard.events.EventSWLabel;
import info.nightscout.utils.SP;
public class SWEditUrl extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWEditUrl.class);
public SWEditUrl() {
super(Type.URL);
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
TextView l = new TextView(context);
l.setId(View.generateViewId());
l.setText(label);
l.setTypeface(l.getTypeface(), Typeface.BOLD);
layout.addView(l);
TextView c = new TextView(context);
c.setId(View.generateViewId());
c.setText(comment);
c.setTypeface(c.getTypeface(), Typeface.ITALIC);
layout.addView(c);
EditText editText = new EditText(context);
editText.setId(View.generateViewId());
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setMaxLines(1);
editText.setText(SP.getString(preferenceId, ""));
layout.addView(editText);
super.generateDialog(view, layout);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (Patterns.WEB_URL.matcher(s).matches())
save(s.toString());
else
MainApp.bus().post(new EventSWLabel(MainApp.gs(R.string.error_url_not_valid)));
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
public SWEditUrl preferenceId(int preferenceId) {
this.preferenceId = preferenceId;
return this;
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.LinearLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.setupwizard.SWDefinition;
public class SWFragment extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWFragment.class);
SWDefinition definition;
Fragment fragment;
public SWFragment(SWDefinition definition) {
super(Type.FRAGMENT);
this.definition = definition;
}
public SWFragment add(Fragment fragment) {
this.fragment = fragment;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
definition.getActivity().getSupportFragmentManager().beginTransaction().add(layout.getId(), fragment, fragment.getTag()).commit();
}
}

View file

@ -0,0 +1,63 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.text.util.Linkify;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.setupwizard.SWValidator;
public class SWHtmlLink extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWHtmlLink.class);
private String textLabel = null;
private TextView l;
private SWValidator visibilityValidator;
public SWHtmlLink() {
super(Type.HTMLLINK);
}
public SWHtmlLink label(int label) {
this.label = label;
return this;
}
public SWHtmlLink label(String newLabel){
this.textLabel = newLabel;
return this;
}
public SWHtmlLink visibility(SWValidator visibilityValidator) {
this.visibilityValidator = visibilityValidator;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
l = new TextView(context);
l.setId(View.generateViewId());
l.setAutoLinkMask(Linkify.ALL);
if(textLabel != null)
l.setText(textLabel);
else
l.setText(label);
layout.addView(l);
}
@Override
public void processVisibility() {
if (visibilityValidator != null && !visibilityValidator.isValid())
l.setVisibility(View.GONE);
else
l.setVisibility(View.VISIBLE);
}
}

View file

@ -0,0 +1,61 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.setupwizard.SWValidator;
public class SWInfotext extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWInfotext.class);
private String textLabel = null;
private TextView l;
private SWValidator visibilityValidator;
public SWInfotext() {
super(Type.TEXT);
}
public SWInfotext label(int label) {
this.label = label;
return this;
}
public SWInfotext label(String newLabel){
this.textLabel = newLabel;
return this;
}
public SWInfotext visibility(SWValidator visibilityValidator) {
this.visibilityValidator = visibilityValidator;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
l = new TextView(context);
l.setId(View.generateViewId());
if(textLabel != null)
l.setText(textLabel);
else
l.setText(label);
layout.addView(l);
}
@Override
public void processVisibility() {
if (visibilityValidator != null && !visibilityValidator.isValid())
l.setVisibility(View.GONE);
else
l.setVisibility(View.VISIBLE);
}
}

View file

@ -0,0 +1,86 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.view.View;
import android.widget.LinearLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
import info.nightscout.utils.SP;
public class SWItem {
private static Logger log = LoggerFactory.getLogger(SWItem.class);
public enum Type {
NONE,
TEXT,
HTMLLINK,
BREAK,
LISTENER,
URL,
STRING,
NUMBER,
DECIMALNUMBER,
CHECKBOX,
RADIOBUTTON,
PLUGIN,
BUTTON,
FRAGMENT
}
Type type;
Integer label;
Integer comment;
int preferenceId;
public SWItem(Type type) {
this.type = type;
}
String getLabel() {
return MainApp.gs(label);
}
String getComment() {
if (comment != null)
return MainApp.gs(comment);
else
return "";
}
Type getType() {
return type;
}
public SWItem label(int label) {
this.label = label;
return this;
}
public SWItem comment(int comment) {
this.comment = comment;
return this;
}
public void save(String value) {
SP.putString(preferenceId, value);
MainApp.bus().post(new EventPreferenceChange(preferenceId));
MainApp.bus().post(new EventSWUpdate());
}
public static LinearLayout generateLayout(View view) {
LinearLayout layout = (LinearLayout) view.findViewById(view.getId());
layout.removeAllViews();
return layout;
}
public void generateDialog(View view, LinearLayout layout) {
}
public void processVisibility() {
}
}

View file

@ -0,0 +1,72 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
public class SWPlugin extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWPlugin.class);
private PluginType pType;
private RadioGroup radioGroup;
public SWPlugin() {
super(Type.PLUGIN);
}
public SWPlugin option(PluginType pType) {
this.pType = pType;
return this;
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
radioGroup = new RadioGroup(context);
radioGroup.clearCheck();
ArrayList<PluginBase> pluginsInCategory = MainApp.getSpecificPluginsList(pType);
radioGroup.setOrientation(LinearLayout.VERTICAL);
radioGroup.setVisibility(View.VISIBLE);
for (int i = 0; i < pluginsInCategory.size(); i++) {
RadioButton rdbtn = new RadioButton(context);
PluginBase p = pluginsInCategory.get(i);
rdbtn.setId(View.generateViewId());
rdbtn.setText(p.getName());
if (p.isEnabled(pType))
rdbtn.setChecked(true);
rdbtn.setTag(p);
radioGroup.addView(rdbtn);
}
radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
RadioButton rb = group.findViewById(checkedId);
PluginBase plugin1 = (PluginBase) rb.getTag();
plugin1.setPluginEnabled(pType, rb.isChecked());
plugin1.setFragmentVisible(pType, rb.isChecked());
ConfigBuilderFragment.processOnEnabledCategoryChanged(plugin1, pType);
ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
MainApp.bus().post(new EventConfigBuilderChange());
MainApp.bus().post(new EventSWUpdate());
});
layout.addView(radioGroup);
super.generateDialog(view, layout);
}
}

View file

@ -0,0 +1,73 @@
package info.nightscout.androidaps.setupwizard.elements;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.utils.SP;
public class SWRadioButton extends SWItem {
private static Logger log = LoggerFactory.getLogger(SWRadioButton.class);
int labelsArray;
int valuesArray;
private RadioGroup radioGroup;
public SWRadioButton() {
super(Type.RADIOBUTTON);
}
public SWRadioButton option(int labels, int values) {
this.labelsArray = labels;
this.valuesArray = values;
return this;
}
public String[] labels() {
return MainApp.sResources.getStringArray(labelsArray);
}
public String[] values() {
return MainApp.sResources.getStringArray(valuesArray);
}
@Override
public void generateDialog(View view, LinearLayout layout) {
Context context = view.getContext();
// Get if there is already value in SP
String previousValue = SP.getString(preferenceId, "none");
radioGroup = new RadioGroup(context);
radioGroup.clearCheck();
radioGroup.setOrientation(LinearLayout.VERTICAL);
radioGroup.setVisibility(View.VISIBLE);
for (int i = 0; i < labels().length; i++) {
RadioButton rdbtn = new RadioButton(context);
rdbtn.setId(View.generateViewId());
rdbtn.setText(labels()[i]);
if (previousValue.equals(values()[i]))
rdbtn.setChecked(true);
rdbtn.setTag(i);
radioGroup.addView(rdbtn);
}
radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
int i = (int) group.findViewById(checkedId).getTag();
save(values()[i]);
});
layout.addView(radioGroup);
super.generateDialog(view, layout);
}
public SWRadioButton preferenceId(int preferenceId) {
this.preferenceId = preferenceId;
return this;
}
}

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps.setupwizard.events;
import info.nightscout.androidaps.events.Event;
public class EventSWLabel extends Event {
public String label;
public EventSWLabel(String label) {
this.label = label;
}
}

View file

@ -0,0 +1,14 @@
package info.nightscout.androidaps.setupwizard.events;
import info.nightscout.androidaps.events.Event;
public class EventSWUpdate extends Event {
public boolean redraw = false;
public EventSWUpdate() {
}
public EventSWUpdate(boolean redraw) {
this.redraw = redraw;
}
}

View file

@ -0,0 +1,94 @@
package info.nightscout.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationWithAction;
public class AndroidPermission {
public static final int CASE_STORAGE = 0x1;
public static final int CASE_SMS = 0x2;
public static final int CASE_LOCATION = 0x3;
public static final int CASE_BATTERY = 0x4;
public static void askForPermission(Activity activity, String[] permission, Integer requestCode) {
boolean test = false;
for (int i = 0; i < permission.length; i++) {
test = test || (ContextCompat.checkSelfPermission(activity, permission[i]) != PackageManager.PERMISSION_GRANTED);
}
if (test) {
ActivityCompat.requestPermissions(activity, permission, requestCode);
}
}
public static void askForPermission(Activity activity, String permission, Integer requestCode) {
String[] permissions = {permission};
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(activity, permissions, requestCode);
}
public static boolean checkForPermission(Context context, String permission) {
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
public static synchronized void notifyForSMSPermissions(Activity activity) {
if (SP.getBoolean(R.string.smscommunicator_remotecommandsallowed, false)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (!checkForPermission(activity, Manifest.permission.RECEIVE_SMS)) {
NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_SMS, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT);
notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.RECEIVE_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_MMS}, AndroidPermission.CASE_SMS));
MainApp.bus().post(new EventNewNotification(notification));
} else
MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_SMS));
}
}
}
public static synchronized void notifyForBatteryOptimizationPermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_BATTERY, String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), Notification.URGENT);
notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}, AndroidPermission.CASE_BATTERY));
MainApp.bus().post(new EventNewNotification(notification));
} else
MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_BATTERY));
}
}
public static synchronized void notifyForStoragePermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_STORAGE, MainApp.gs(R.string.needstoragepermission), Notification.URGENT);
notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, AndroidPermission.CASE_STORAGE));
MainApp.bus().post(new EventNewNotification(notification));
} else
MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_STORAGE));
}
}
public static synchronized void notifyForLocationPermissions(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)) {
NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_LOCATION, MainApp.gs(R.string.needlocationpermission), Notification.URGENT);
notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, AndroidPermission.CASE_LOCATION));
MainApp.bus().post(new EventNewNotification(notification));
} else
MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_LOCATION));
}
}
}

View file

@ -33,7 +33,7 @@ import info.nightscout.androidaps.events.EventAppExit;
public class ImportExportPrefs { public class ImportExportPrefs {
private static Logger log = LoggerFactory.getLogger(ImportExportPrefs.class); private static Logger log = LoggerFactory.getLogger(ImportExportPrefs.class);
static File path = new File(Environment.getExternalStorageDirectory().toString()); static File path = new File(Environment.getExternalStorageDirectory().toString());
static final File file = new File(path, MainApp.gs(R.string.app_name) + "Preferences"); static public final File file = new File(path, MainApp.gs(R.string.app_name) + "Preferences");
private static final int REQUEST_EXTERNAL_STORAGE = 1; private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = { private static String[] PERMISSIONS_STORAGE = {

View file

@ -16,6 +16,10 @@ public class SP {
return sharedPreferences.contains(key); return sharedPreferences.contains(key);
} }
static public boolean contains(int resourceId) {
return sharedPreferences.contains(MainApp.gs(resourceId));
}
static public String getString(int resourceID, String defaultValue) { static public String getString(int resourceID, String defaultValue) {
return sharedPreferences.getString(MainApp.gs(resourceID), defaultValue); return sharedPreferences.getString(MainApp.gs(resourceID), defaultValue);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".setupwizard.SetupWizardActivity">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:background="@android:color/transparent"
android:onClick="exitPressed"
app:srcCompat="@drawable/ic_exit_to_app" />
<TextView
android:id="@+id/sw_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:keepScreenOn="true"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:textSize="32sp"
tools:text="Title" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="@+id/sw_content_fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:orientation="vertical"
android:padding="16dp" />
</ScrollView>
<LinearLayout
android:id="@+id/sw_content_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/black_overlay"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<Button
android:id="@+id/previous_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="showPreviousPage"
android:text="@string/setupwizard_previous"
android:textColor="#FFFFFF" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<Button
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="showNextPage"
android:text="@string/setupwizard_next"
android:textColor="#FFFFFF" />
<Button
android:id="@+id/finish_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="finishSetupWizard"
android:text="@string/setupwizard_finish"
android:textColor="#FFFFFF" />
</LinearLayout>
</LinearLayout>

View file

@ -7,6 +7,9 @@
<item <item
android:id="@+id/nav_historybrowser" android:id="@+id/nav_historybrowser"
android:title="@string/nav_historybrowser" /> android:title="@string/nav_historybrowser" />
<item
android:id="@+id/nav_setupwizard"
android:title="@string/nav_setupwizard" />
<item <item
android:id="@+id/nav_resetdb" android:id="@+id/nav_resetdb"
android:title="@string/nav_resetdb" /> android:title="@string/nav_resetdb" />

View file

@ -71,7 +71,7 @@
<string name="objectives">Цели</string> <string name="objectives">Цели</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Общ</string> <string name="overview">Общ</string>
<string name="profileviewer">NS Профил</string> <string name="nsprofile">NS Профил</string>
<string name="simpleprofile">Обикновен профил</string> <string name="simpleprofile">Обикновен профил</string>
<string name="tempbasal">TempBasal</string> <string name="tempbasal">TempBasal</string>
<string name="treatments">Лечения</string> <string name="treatments">Лечения</string>

View file

@ -110,7 +110,7 @@
<string name="overview_newtempbasal_basalpercent">Hodnota bazálu [%]</string> <string name="overview_newtempbasal_basalpercent">Hodnota bazálu [%]</string>
<string name="overview_newtempbasal_percent_label">% (100% = současný)</string> <string name="overview_newtempbasal_percent_label">% (100% = současný)</string>
<string name="overview_treatment_label">Bolus</string> <string name="overview_treatment_label">Bolus</string>
<string name="profileviewer">NS profil</string> <string name="nsprofile">NS profil</string>
<string name="objectives_pumpstatusavailableinns">Stav pumpy dostupný v NS</string> <string name="objectives_pumpstatusavailableinns">Stav pumpy dostupný v NS</string>
<string name="rate">Hodnota</string> <string name="rate">Hodnota</string>
<string name="reason">Zdůvodnění</string> <string name="reason">Zdůvodnění</string>
@ -545,7 +545,7 @@
<string name="overview_extendedbolus_cancel_button">Zrušit prodloužený bolus</string> <string name="overview_extendedbolus_cancel_button">Zrušit prodloužený bolus</string>
<string name="overview_newtempbasal_basalabsolute">Hodnota bazálu [U/h]</string> <string name="overview_newtempbasal_basalabsolute">Hodnota bazálu [U/h]</string>
<string name="overview_newtempbasal_basaltype_label">Typ bazálu</string> <string name="overview_newtempbasal_basaltype_label">Typ bazálu</string>
<string name="profileswitch">PřepnutíProfilu</string> <string name="profileswitch">Přepnutí profilu</string>
<string name="pump">Pumpa</string> <string name="pump">Pumpa</string>
<string name="xdripstatus">Statusový řádek xDripu (hodinky)</string> <string name="xdripstatus">Statusový řádek xDripu (hodinky)</string>
<string name="xdripstatus_settings">Status z xDripu (hodinky)</string> <string name="xdripstatus_settings">Status z xDripu (hodinky)</string>

View file

@ -16,7 +16,7 @@
<string name="days">Tage</string> <string name="days">Tage</string>
<string name="ok">OK</string> <string name="ok">OK</string>
<string name="openapsma_profile_label">Profil</string> <string name="openapsma_profile_label">Profil</string>
<string name="profileviewer">Nightscout-Profil</string> <string name="nsprofile">Nightscout-Profil</string>
<string name="tempbasals_iob_label_string">IOB:</string> <string name="tempbasals_iob_label_string">IOB:</string>
<string name="tempbasals_iobtotal_label_string">Gesamt-IOB:</string> <string name="tempbasals_iobtotal_label_string">Gesamt-IOB:</string>
<string name="tempbasals_netinsulin_label_string">Ins:</string> <string name="tempbasals_netinsulin_label_string">Ins:</string>

View file

@ -72,7 +72,7 @@
<string name="objectives">Στόχοι</string> <string name="objectives">Στόχοι</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Επισκόπηση</string> <string name="overview">Επισκόπηση</string>
<string name="profileviewer">Προφίλ NS</string> <string name="nsprofile">Προφίλ NS</string>
<string name="simpleprofile">Απλό Προφίλ</string> <string name="simpleprofile">Απλό Προφίλ</string>
<string name="tempbasal">Προσ.Ρυθμός</string> <string name="tempbasal">Προσ.Ρυθμός</string>
<string name="treatments">Θεραπείες</string> <string name="treatments">Θεραπείες</string>

View file

@ -71,7 +71,7 @@
<string name="objectives">Objetivos</string> <string name="objectives">Objetivos</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Sinopsis</string> <string name="overview">Sinopsis</string>
<string name="profileviewer">Perfil NS</string> <string name="nsprofile">Perfil NS</string>
<string name="simpleprofile">Perfil simple</string> <string name="simpleprofile">Perfil simple</string>
<string name="tempbasal">Basal temporal</string> <string name="tempbasal">Basal temporal</string>
<string name="treatments">Tratamientos</string> <string name="treatments">Tratamientos</string>

View file

@ -67,7 +67,7 @@
<string name="objectives">Objectifs</string> <string name="objectives">Objectifs</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Aperçu</string> <string name="overview">Aperçu</string>
<string name="profileviewer">Profil NS</string> <string name="nsprofile">Profil NS</string>
<string name="simpleprofile">Profil simple</string> <string name="simpleprofile">Profil simple</string>
<string name="tempbasal">Basal Tempo</string> <string name="tempbasal">Basal Tempo</string>
<string name="treatments">Traitements</string> <string name="treatments">Traitements</string>

View file

@ -454,7 +454,7 @@
<string name="simpleprofile_shortname">SP</string> <string name="simpleprofile_shortname">SP</string>
<string name="quickwizard">QuickWizard</string> <string name="quickwizard">QuickWizard</string>
<string name="quickwizardsettings">Impostazioni QuickWizard</string> <string name="quickwizardsettings">Impostazioni QuickWizard</string>
<string name="profileviewer">Profilo NS</string> <string name="nsprofile">Profilo NS</string>
<string name="profile_set_ok">Profilo Basale aggiornato nel Micro</string> <string name="profile_set_ok">Profilo Basale aggiornato nel Micro</string>
<string name="profile_set_failed">Impostazione Profilo Basale fallito</string> <string name="profile_set_failed">Impostazione Profilo Basale fallito</string>
</resources> </resources>

View file

@ -71,7 +71,7 @@
<string name="objectives">목표</string> <string name="objectives">목표</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">개요</string> <string name="overview">개요</string>
<string name="profileviewer">NS 프로파일</string> <string name="nsprofile">NS 프로파일</string>
<string name="simpleprofile">Simple 프로파일</string> <string name="simpleprofile">Simple 프로파일</string>
<string name="tempbasal">임시기초</string> <string name="tempbasal">임시기초</string>
<string name="treatments">관리</string> <string name="treatments">관리</string>

View file

@ -426,7 +426,7 @@
<string name="openapsma_inputparameters_label">Berekende gegevens</string> <string name="openapsma_inputparameters_label">Berekende gegevens</string>
<string name="openapsma_iobdata_label">IOB gegevens</string> <string name="openapsma_iobdata_label">IOB gegevens</string>
<string name="openapsma_maxbasal_summary">DIt is de maximale waarde waarop het basaal door OpenAPS ingesteld kan worden</string> <string name="openapsma_maxbasal_summary">DIt is de maximale waarde waarop het basaal door OpenAPS ingesteld kan worden</string>
<string name="profileviewer">NS Profiel</string> <string name="nsprofile">NS Profiel</string>
<string name="profileviewer_shortname">NSPROFIEL</string> <string name="profileviewer_shortname">NSPROFIEL</string>
<string name="pump">Pomp</string> <string name="pump">Pomp</string>
<string name="overview_tempbasal_button">Tijdelijk basaal</string> <string name="overview_tempbasal_button">Tijdelijk basaal</string>

View file

@ -75,7 +75,7 @@
<string name="objectives">Zadania</string> <string name="objectives">Zadania</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Przegląd</string> <string name="overview">Przegląd</string>
<string name="profileviewer">NS Profil</string> <string name="nsprofile">NS Profil</string>
<string name="simpleprofile">Prosty profil</string> <string name="simpleprofile">Prosty profil</string>
<string name="tempbasal">TymczasowaBaza</string> <string name="tempbasal">TymczasowaBaza</string>
<string name="treatments">Leczenie</string> <string name="treatments">Leczenie</string>

View file

@ -69,7 +69,7 @@
<string name="objectives">Obiective</string> <string name="objectives">Obiective</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Privire ansamblu</string> <string name="overview">Privire ansamblu</string>
<string name="profileviewer">Profil NS</string> <string name="nsprofile">Profil NS</string>
<string name="simpleprofile">Profil simplu</string> <string name="simpleprofile">Profil simplu</string>
<string name="treatments">Tratamente</string> <string name="treatments">Tratamente</string>
<string name="virtualpump">Pompă virtuală</string> <string name="virtualpump">Pompă virtuală</string>

View file

@ -374,7 +374,7 @@
<string name="profile">профиль</string> <string name="profile">профиль</string>
<string name="profile_set_failed">настройка базального профиля не состоялась</string> <string name="profile_set_failed">настройка базального профиля не состоялась</string>
<string name="profile_set_ok">базальный профиль помпы обновлен</string> <string name="profile_set_ok">базальный профиль помпы обновлен</string>
<string name="profileviewer">профиль NS</string> <string name="nsprofile">профиль NS</string>
<string name="profileviewer_shortname">профильNS</string> <string name="profileviewer_shortname">профильNS</string>
<string name="pumpNotInitialized">помпа не инициализирована</string> <string name="pumpNotInitialized">помпа не инициализирована</string>
<string name="pumpNotInitializedProfileNotSet">помпа не инициализирована, профиль не установлен</string> <string name="pumpNotInitializedProfileNotSet">помпа не инициализирована, профиль не установлен</string>

View file

@ -430,7 +430,7 @@
<string name="pumpNotInitialized">Pump inte initierad</string> <string name="pumpNotInitialized">Pump inte initierad</string>
<string name="pump">Pump</string> <string name="pump">Pump</string>
<string name="profileviewer_shortname">NSProfil</string> <string name="profileviewer_shortname">NSProfil</string>
<string name="profileviewer">NS-profil</string> <string name="nsprofile">NS-profil</string>
<string name="profileswitch">Profilbyte</string> <string name="profileswitch">Profilbyte</string>
<string name="profile_set_ok">Basalprofilen uppdaterad i pumpen</string> <string name="profile_set_ok">Basalprofilen uppdaterad i pumpen</string>
<string name="profile_set_failed">Lyckades inte sätta basalprofilen</string> <string name="profile_set_failed">Lyckades inte sätta basalprofilen</string>

View file

@ -109,5 +109,4 @@
<item>@string/no</item> <item>@string/no</item>
<item>@string/yes</item> <item>@string/yes</item>
</string-array> </string-array>
</resources> </resources>

View file

@ -68,9 +68,16 @@
<color name="notificationLow">#ff827c</color> <color name="notificationLow">#ff827c</color>
<color name="notificationInfo">#009705</color> <color name="notificationInfo">#009705</color>
<color name="black_overlay">#66000000</color>
<color name="deviationgrey">#c8666666</color> <color name="deviationgrey">#c8666666</color>
<color name="deviationgreen">#7200FF00</color> <color name="deviationgreen">#7200FF00</color>
<color name="deviationred">#72FF0000</color> <color name="deviationred">#72FF0000</color>
<color name="deviationblack">#72000000</color> <color name="deviationblack">#72000000</color>
<color name="swColorPrimary">#303030</color>
<color name="swColorPrimaryDark">#303030</color>
<color name="swColorAccent">#FFEB3B</color>
<color name="swColorBackground">#303030</color>
</resources> </resources>

View file

@ -74,7 +74,7 @@
<string name="objectives">Objectives</string> <string name="objectives">Objectives</string>
<string name="openapsma">OpenAPS MA</string> <string name="openapsma">OpenAPS MA</string>
<string name="overview">Overview</string> <string name="overview">Overview</string>
<string name="profileviewer">NS Profile</string> <string name="nsprofile">NS Profile</string>
<string name="simpleprofile">Simple profile</string> <string name="simpleprofile">Simple profile</string>
<string name="tempbasal">TempBasal</string> <string name="tempbasal">TempBasal</string>
<string name="treatments">Treatments</string> <string name="treatments">Treatments</string>
@ -485,7 +485,7 @@
<string name="restart">Restart</string> <string name="restart">Restart</string>
<string name="nsclientinternal_title">NSClient</string> <string name="nsclientinternal_title">NSClient</string>
<string name="nsclientinternal_url_title">Nightscout URL</string> <string name="nsclientinternal_url_title">Nightscout URL</string>
<string name="nsclientinternal_url_dialogmessage">Enter Nightscout URL</string> <string name="nsclientinternal_url_dialogmessage">Enter Your Nightscout URL</string>
<string name="nsclientinternal_secret_title">NS API secret</string> <string name="nsclientinternal_secret_title">NS API secret</string>
<string name="nsclientinternal_secret_dialogtitle">NS API secret</string> <string name="nsclientinternal_secret_dialogtitle">NS API secret</string>
<string name="nsclientinternal_secret_dialogmessage">Enter NS API secret (min 12 chars)</string> <string name="nsclientinternal_secret_dialogmessage">Enter NS API secret (min 12 chars)</string>
@ -667,6 +667,7 @@
<string name="free_peak_oref">Free-Peak Oref</string> <string name="free_peak_oref">Free-Peak Oref</string>
<string name="rapid_acting_oref">Rapid-Acting Oref</string> <string name="rapid_acting_oref">Rapid-Acting Oref</string>
<string name="ultrarapid_oref">Ultra-Rapid Oref</string> <string name="ultrarapid_oref">Ultra-Rapid Oref</string>
<string name="free_peak_oref_description">Custom insulin</string>
<string name="dia_too_short" formatted="false">DIA of %f too short - using %f instead!</string> <string name="dia_too_short" formatted="false">DIA of %f too short - using %f instead!</string>
<string name="activate_profile">Activate profile</string> <string name="activate_profile">Activate profile</string>
<string name="date">Date</string> <string name="date">Date</string>
@ -1009,6 +1010,17 @@
<string name="time">Time</string> <string name="time">Time</string>
<string name="key_show_notes_entry_dialogs" translatable="false">show_notes_entry_dialogs</string> <string name="key_show_notes_entry_dialogs" translatable="false">show_notes_entry_dialogs</string>
<string name="overview_show_notes_field_in_dialogs_title">Show notes field in treatment dialogs</string> <string name="overview_show_notes_field_in_dialogs_title">Show notes field in treatment dialogs</string>
<string name="title_activity_setup_wizard">SetupWizardActivity</string>
<string name="next_button">Next</string>
<string name="previous_button">Prev</string>
<string name="skip_button">Skip</string>
<string name="nav_setupwizard">Setup Wizard</string>
<string name="setupwizard_next">Next</string>
<string name="setupwizard_previous">Prev</string>
<string name="setupwizard_skip">Skip</string>
<string name="setupwizard_finish">FINISH</string>
<string name="setupwizard_language_prompt">Select your language</string>
<string name="key_language" translatable="false">language</string>
<string name="key_openapsama_min_5m_carbimpact" translatable="false">openapsama_min_5m_carbimpact</string> <string name="key_openapsama_min_5m_carbimpact" translatable="false">openapsama_min_5m_carbimpact</string>
<string name="boluserrorcode">Asked: %.2fU Delivered: %.2fU Error code: %d</string> <string name="boluserrorcode">Asked: %.2fU Delivered: %.2fU Error code: %d</string>
<string name="firstinsulinincrement">First insulin increment</string> <string name="firstinsulinincrement">First insulin increment</string>
@ -1047,4 +1059,31 @@
<string name="wear_wizard_settings_summary">Calculations included in the Wizard result:</string> <string name="wear_wizard_settings_summary">Calculations included in the Wizard result:</string>
<string name="wear_display_settings">Display Settings</string> <string name="wear_display_settings">Display Settings</string>
<string name="wear_general_settings">General Settings</string> <string name="wear_general_settings">General Settings</string>
<string name="enable_nsclient">Enable NSClient</string>
<string name="welcometosetupwizard">Welcome to setup wizard. It will guide you through the setup process\n</string>
<string name="pumpsetup">Pump setup</string>
<string name="readstatus">Read status</string>
<string name="adjustprofileinns">Changes must be done in NS</string>
<string name="exitwizard">Skip setup wizard</string>
<string name="setupwizard_bgsource_description">Where should blood glucose(BG) data be comming from ?\n</string>
<string name="setupwizard_loop_description">Press the button below to enable AndroidAPS to suggest/make basal changes</string>
<string name="setupwizard_objectives_description">Press the button below to enable Objectives. Look in the Objectives tab, after you finish this wizard, to make AndroidAPS completely functional.\n</string>
<string name="enableobjectives">Enable Objectives</string>
<string name="apssetup">Configure APS plugin</string>
<string name="backupismissing">Exported configuration is missing thus import configuration is not possible.\n</string>
<string name="key_setupwizard_processed" translatable="false">startupwizard_processed</string>
<string name="sensitivitysetup">Configure Sensitivity plugin</string>
<string name="setupwizard_sensitivity_description">Sensitivity plugin is used for sensitivity detection and COB calculation. For more info visit:</string>
<string name="setupwizard_sensitivity_url">https://github.com/MilosKozak/AndroidAPS/wiki/Sensitivity-detection-and-COB</string>
<string name="nsclientinfotext">NSClient handles connection to Nightscout. You can skip this part now but you will not be able to pass objectives until you setup it.</string>
<string name="diawarning">Please remember: new insulin profiles require DIA at least 5h. DIA 5-6h on new profile is equal to DIA 3h on old insulin profiles.</string>
<string name="bgsourcesetup">Configure BG source</string>
<string name="setupwizard_profile_description">Please select source of profile. If patient is a child you should use NS profile. If there is nobody following you on Nightscout you will probably prefer Local profile. Please remember that you are only selecting the profile source. To use it you must activate it by executing \"Profile switch\"</string>
<string name="setupwizard_aps_description">Select one from availables algorithms. They are sorted from oldest to newest. Newer algorithm is usualy more powerfull and more aggresive. Thus if you are new looper you may probably start with AMA and not with latest one. Do not forget to read the OpenAPS documentation and configure it before use.</string>
<string name="startobjective">Start your first objective</string>
<string name="permission">Permission</string>
<string name="askforpermission">Ask for permission</string>
<string name="needlocationpermission">Application needs location permission for BT scan</string>
<string name="needstoragepermission">Application needs storage permission to be able store log files</string>
<string name="request">Request</string>
</resources> </resources>

View file

@ -24,5 +24,12 @@
<item name="android:textSize">10sp</item> <item name="android:textSize">10sp</item>
</style> </style>
<!-- Preferences --> <style name="AppTheme.SetupWizard" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/swColorPrimary</item>
<item name="colorPrimaryDark">@color/swColorPrimaryDark</item>
<item name="colorAccent">@color/swColorAccent</item>
<item name="android:windowBackground">@color/swColorBackground</item>
</style>
<!-- Preferences -->
</resources> </resources>