setupwizard template

This commit is contained in:
Milos Kozak 2018-04-20 17:27:31 +02:00
parent 645e83b6e6
commit b554d641a7
18 changed files with 474 additions and 7 deletions

View file

@ -49,7 +49,7 @@ def generateGitBuild = { ->
return stringBuilder.toString()
}
tasks.matching {it instanceof Test}.all {
tasks.matching { it instanceof Test }.all {
testLogging.events = ["failed", "skipped", "started"]
testLogging.exceptionFormat = "full"
}
@ -89,7 +89,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
testCoverageEnabled (project.hasProperty('coverage') ? true : false)
testCoverageEnabled(project.hasProperty('coverage') ? true : false)
}
}
productFlavors {
@ -156,7 +156,7 @@ android {
unitTests.returnDefaultValues = true
unitTests.includeAndroidResources = true
}
}
}
allprojects {
repositories {
@ -172,6 +172,7 @@ configurations {
}
dependencies {
implementation 'com.android.support:support-v4:27.1.1'
wearApp project(':wear')
implementation fileTree(include: ['*.jar'], dir: 'libs')
@ -242,7 +243,7 @@ dependencies {
}
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 outputDir = file("${buildDir}/unpacked/dist")

View file

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

View file

@ -49,6 +49,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.startupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.SlidingTabLayout;
import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.utils.ImportExportPrefs;
@ -368,6 +369,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.nav_historybrowser:
startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
break;
case R.id.nav_setupwizard:
startActivity(new Intent(v.getContext(), SetupWizardActivity.class));
break;
case R.id.nav_resetdb:
new AlertDialog.Builder(v.getContext())
.setTitle(R.string.nav_resetdb)

View file

@ -0,0 +1,46 @@
package info.nightscout.androidaps.startupwizard;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
import info.nightscout.utils.SP;
public class SWDefinition {
private static SWDefinition swDefinition = null;
public static SWDefinition getInstance() {
if (swDefinition == null)
swDefinition = new SWDefinition();
return swDefinition;
}
static List<SWScreen> screens = new ArrayList<>();
public static List<SWScreen> getScreens() {
return screens;
}
SWDefinition add(SWScreen newScreen) {
screens.add(newScreen);
return this;
}
SWDefinition() {
add(new SWScreen(R.string.nsclientinternal_title)
.skippable(false)
.add(new SWUrl().preferenceId(R.string.key_nsclientinternal_url).label(R.string.nsclientinternal_url_title).comment(R.string.nsclientinternal_url_dialogmessage))
.add(new SWString().preferenceId(R.string.key_nsclientinternal_api_secret).label(R.string.nsclientinternal_secret_dialogtitle).comment(R.string.nsclientinternal_secret_dialogmessage))
.validator(() -> NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)
)
.add(new SWScreen(R.string.patientage)
.skippable(false)
.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))
)
;
}
}

View file

@ -0,0 +1,62 @@
package info.nightscout.androidaps.startupwizard;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.utils.SP;
public class SWItem {
enum Type {
NONE,
URL,
STRING,
NUMBER,
DECIMALNUMBER,
CHECKBOX,
RADIOBUTTON
}
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;
}
SWItem preferenceId(int preferenceId) {
this.preferenceId = preferenceId;
return this;
}
public void save(String value) {
SP.putString(preferenceId, value);
MainApp.bus().post(new EventPreferenceChange(preferenceId));
}
}

View file

@ -0,0 +1,28 @@
package info.nightscout.androidaps.startupwizard;
import info.nightscout.androidaps.MainApp;
public class SWRadioButton extends SWItem {
int labelsArray;
int valuesArray;
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);
}
}

View file

@ -0,0 +1,43 @@
package info.nightscout.androidaps.startupwizard;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
public class SWScreen {
int header;
List<SWItem> items = new ArrayList<>();
SWValidator validator;
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;
}
boolean isValid() {
if (validator != null)
return validator.isValid();
return true;
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.startupwizard;
public class SWString extends SWItem {
public SWString() {
super(Type.STRING);
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.startupwizard;
public class SWUrl extends SWItem {
public SWUrl() {
super(Type.URL);
}
}

View file

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

View file

@ -0,0 +1,165 @@
package info.nightscout.androidaps.startupwizard;
import android.annotation.SuppressLint;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import info.nightscout.androidaps.R;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
public class SetupWizardActivity extends AppCompatActivity {
/**
* Whether or not the system UI should be auto-hidden after
* {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300;
private final Handler mHideHandler = new Handler();
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable() {
@SuppressLint("InlinedApi")
@Override
public void run() {
// Delayed removal of status and navigation bar
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
};
private View mControlsView;
private final Runnable mShowPart2Runnable = new Runnable() {
@Override
public void run() {
// Delayed display of UI elements
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
mControlsView.setVisibility(View.VISIBLE);
}
};
private boolean mVisible;
private final Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
hide();
}
};
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
private final View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setupwizard);
mVisible = true;
mControlsView = findViewById(R.id.fullscreen_content_controls);
mContentView = findViewById(R.id.fullscreen_content);
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
toggle();
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
private void toggle() {
if (mVisible) {
hide();
} else {
show();
}
}
private void hide() {
// Hide UI first
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
mControlsView.setVisibility(View.GONE);
mVisible = false;
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler.removeCallbacks(mShowPart2Runnable);
mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}
@SuppressLint("InlinedApi")
private void show() {
// Show the system bar
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mVisible = true;
// Schedule a runnable to display UI elements after a delay
mHideHandler.removeCallbacks(mHidePart2Runnable);
mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
}
/**
* Schedules a call to hide() in delay milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
}

View file

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

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".startupwizard.SetupWizardActivity">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<TextView
android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="@string/dummy_content"
android:textColor="#33b5e5"
android:textSize="50sp"
android:textStyle="bold" />
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/fullscreen_content_controls"
style="?metaButtonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/black_overlay"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button
android:id="@+id/dummy_button"
style="?metaButtonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button" />
</LinearLayout>
</FrameLayout>
</FrameLayout>

View file

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

View file

@ -0,0 +1,12 @@
<resources>
<!-- Declare custom theme attributes that allow changing which styles are
used for button bars depending on the API level.
?android:attr/buttonBarStyle is new as of API 11 so this is
necessary to support previous API levels. -->
<declare-styleable name="ButtonBarContainerTheme">
<attr name="metaButtonBarStyle" format="reference" />
<attr name="metaButtonBarButtonStyle" format="reference" />
</declare-styleable>
</resources>

View file

@ -62,4 +62,6 @@
<color name="notificationLow">#ff827c</color>
<color name="notificationInfo">#009705</color>
<color name="black_overlay">#66000000</color>
</resources>

View file

@ -1000,4 +1000,9 @@
<string name="time">Time</string>
<string name="key_show_notes_entry_dialogs">show_notes_entry_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="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="nav_setupwizard">Setup Wizard</string>
</resources>

View file

@ -24,5 +24,17 @@
<item name="android:textSize">10sp</item>
</style>
<style name="FullscreenTheme" parent="AppTheme">
<item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
<item name="metaButtonBarStyle">?android:attr/buttonBarStyle</item>
<item name="metaButtonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
</style>
<style name="FullscreenActionBarStyle" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<!-- Preferences -->
</resources>